状态更改时 React 组件未更新

Posted

技术标签:

【中文标题】状态更改时 React 组件未更新【英文标题】:React Component not updated when state changes 【发布时间】:2018-09-21 21:46:23 【问题描述】:

我有一个输入等待一个 URL 和一个下拉列表。根据 URL,下拉列表中的列表会有所不同。 我为下拉菜单创建了一个组件(LocationSelector)。加载页面时输入为空。

我的问题是,当我将 URL 放入输入中并且状态数据得到更新时,组件不会更新。

这是处理输入的页面代码(我剪掉了一些部分):

import React,  Component  from "react";
import LocationSelector from "../component/location-selector";

class Manage extends Component 
  constructor(props) 
    super(props);

    this.state = 
      ProductURL: ""
    ;

    this.handleChange = this.handleChange.bind(this);
    this.addProduct = this.addProduct.bind(this);
  

  handleChange(event) 
    this.setState( [event.target.name]: event.target.value );
  

  addProduct(event) 
    // Do stuff
  

  render() 
    return (
      <div className="col-md-6">
            <div className="row">
              <div className="col-md-12">
                <h2 className="bottom-separator">Add a product</h2>
              </div>

              <form onSubmit=this.addProduct>
                <div className="col-md-12 margin-bottom-10">
                  <label>URL :</label>
                  <input
                    type="text"
                    className="form-control"
                    name="ProductURL"
                    value=this.state.ProductURL
                    onChange=this.handleChange
                  />
                </div>
                <div className="col-md-12 margin-bottom-10">
                  <LocationSelector
                    label="Shop"
                    location=this.state.ProductURL.split(".")[1]
                  />
                </div>
                <div className="col-md-12">
                  <input
                    type="submit"
                    value="Submit"
                    className="btn btn-primary"
                  />
                </div>
              </form>
            </div>
          </div>
    );
  

这是我的组件 LocationSelector 的代码:

import React,  Component  from "react";

var data = require("../service/data");

class MySelectOptions extends Component 
  /**
   * Returns an Option element containing an ActorLocation to put in a Select element.
   * @props :
   *  -data.id : the id of the ActorLocation (ex : "5001")
   *  -data.value : the name of the ActorLocation (ex : "NY")
   *  -data.subvalue : the subtext of the ActorLocation (ex : "subtext")
   */

  render() 
    return (
      <option
        data-subtext=this.props.data.subvalue
        value=this.props.data.id
      >
        this.props.data.value
      </option>
    );
  


class LocationSelector extends Component 
  /**
   * Returns a dropdown menu filled with the ActorLocation of a specific Actor.
   * @props :
   *  -label : the name of the Actor written in a normal way (ex : "My Actor")
   *  -location : the name of the Actor to be put in the URL request (ex : "myactor")
   */

  constructor(props) 
    super(props);

    this.state = 
      locations: []
    ;
    this.componentDidMount = this.componentDidMount.bind(this);
    this.componentWillUnmount = this.componentWillUnmount.bind(this);
  

  componentDidMount() 
    let vm = this;

    this.request = data.actors.get(vm.props.location).then(function(data) 
      var items = [];
      if (!jQuery.isEmptyObject(data)) 
        data.locations.forEach(function(location) 
          items.push(
            id: location.id,
            value: location.name,
            subvalue: location.subText
          );
        );
      
      vm.setState( locations: items );
      $(".selectpicker").selectpicker("refresh");
    );
  

  componentWillUnmount() 
    if (this.request) 
      this.request.cancel();
    
  

  render() 
    var i = 0;
    var mySelectOptions = function(result) 
      return <MySelectOptions key=i++ data=result />;
    ;

    let selectId = "locationSelector" + this.props.label.replace(" ", "");

    return (
      <div>
        <label htmlFor="products">this.props.label:</label>
        <select
          id=selectId
          className="selectpicker show-tick"
          data-live-search="true"
          data-size="5"
        >
          this.state.locations.map(mySelectOptions)
        </select>
      </div>
    );
  


export default LocationSelector;

感谢您的帮助!

编辑

这是一个几乎可以工作的 CodeSandbox:https://codesandbox.io/s/m4x04mw3wx

【问题讨论】:

你能用 CodingSandbox.io 创建一个工作版本吗?只是让它更容易使用。 我做了一个沙盒,但我无法正确设置它... Manage.jsx 文件不想转译。我把链接放在问题中。 【参考方案1】:

您需要使用 React 生命周期更新方法来执行该操作。见:https://reactjs.org/docs/react-component.html#the-component-lifecycle

将此添加到您的 LocationSelector 类中:

componentWillReceiveProps(newProps)
    this.setState(
        location: newProps.location
    )

【讨论】:

感谢您的帮助!完美工作:)

以上是关于状态更改时 React 组件未更新的主要内容,如果未能解决你的问题,请参考以下文章

无法对未安装的组件执行 React 状态更新(useEffect 反应挂钩)

表单输入的值在 React 中提交时未更新

React Context 组件在状态更改时不会更新

反应钩子。无法对未安装的组件执行 React 状态更新

React useEffect 抛出错误:无法对未安装的组件执行 React 状态更新

React 功能组件中状态更改后组件未重新渲染