【问题标题】:I am updating my state using this.setState but still i am recieving the old values in render()我正在使用 this.setState 更新我的状态,但我仍然在 render() 中接收旧值
【发布时间】:2021-07-16 07:32:13
【问题描述】:
class EditLocation extends Component {
  constructor(props) {
   super();
    this.state = {
      LocationId: '',
      locationOptions: [],
    }
    this.baseState = this.state;
    this.findLocationById = this.findLocationById.bind(this);

}
findLocationById = (locationId) => {
  let locationOptions = [];
  if (locationId <= 0) {
    setTimeout(()=>{
      this.setState(this.baseState);
      locationOptions.push(
        <CustomInput
        type="checkbox"
        id={value.LocationTypeId}
        key={value.LocationTypeId}
        value={value.LocationTypeId}
        defaultChecked={false}
        label={`${value.LocationTypeName}`}
        className="mb-0"
        onChange={this.handleCheckbox.bind(this)}
      />
      )
      this.setState({locationOptions:locationOptions})
    },200)
    else {
      setTimeout(() => {
      let location = this.props.store.selectedLocation;
      this.props.store.LocationTypes.forEach((value)=>{
        if(location.LocationTypes ? 
         location.LocationTypes.includes(value.LocationTypeId): false)
        {
          locationOptions.push(
            <CustomInput
            type="checkbox"
            id={value.LocationTypeId}
            key={value.LocationTypeId}
            value={value.LocationTypeId}
            defaultChecked={true}
            label={`${value.LocationTypeName}`}
            className="mb-0"
            onChange={this.handleCheckbox.bind(this)}
          />
          )
        }
        else
        {
          locationOptions.push(
            <CustomInput
            type="checkbox"
            id={value.LocationTypeId}
            key={value.LocationTypeId}
            value={value.LocationTypeId}
            defaultChecked={false}
            label={`${value.LocationTypeName}`}
            className="mb-0"
            onChange={this.handleCheckbox.bind(this)}
          />
          )
        }
      })
    this.setState({
       LocationId: location.LocationId,
       locationOptions: locationOptions,
    })
   

   render(){
  return (
   <div>
    <Modal>
      <Form>
         <FormGroup>
           <input
            value={this.state.LocationId}
            type="text"
            name="Location"
            id="Location"      
           />
         </FormGroup>
         <FormGroup>
           {console.log(this.state.locationOptions)} // showing updated state value
           {this.state.locationOptions} // showing previous state.locationOptions value
         </FormGroup>
        </Form>
    </Modal>
   </div>
   )
}

}

渲染中的

console.log() 正在更新值,因为我对 customInput 的检查没有更新。我需要重新打开模式或重新加载整个程序以查看更新。 任何解决方案和资源都会有所帮助,因为我坚持了几个小时并且似乎无法解决问题。如果有帮助,商店就是 mobx 商店

【问题讨论】:

  • 不要在渲染中使用 console.log,这是一个无意的副作用。状态更新时使用componentDidUpdate 记录。
  • 并且 locationId 已更新并在 内显示为已更新,但复选框不起作用。我知道 setState 是异步的,但我不知道如何使用它的回调在渲染中实现真正的更新
  • @DrewReese 但console.log 不是主要问题。我需要 {this.state.locationOptions} 来显示实际价值以及我如何实现这一目标
  • this.state始终当前状态。您还在 findLocationById 中做了一些奇怪的事情,例如将 JSX 存储在状态中(一种 React 反模式),这几乎可以保证在外壳中具有陈旧的值,并在超时时将状态更新入队,所以谁知道你会在未来哪个渲染周期看到该更新。
  • findLocationById 下面调用并检查语法

标签: javascript reactjs setstate


【解决方案1】:

您以错误的方式使用 setState。

setState() 将组件状态的变化加入队列并告诉 React 这个组件及其子组件需要重新渲染 更新状态。这是您用来更新用户的主要方法 响应事件处理程序和服务器响应的接口。

React docs

  1. 所以它是异步的,你不能保证什么时候更新。
  2. 在 React 中使用 setTimeout 是一种不礼貌的行为。
  3. 以状态存储整个组件,例如locationOptions 也不是好主意。
  4. 最好将输入移动到单独的组件,因为我看到只有 defaultChecked 不同。
  5. 更好地使用 Hooks,在 React 的方式中更容易考虑这一点,这需要一些时间和精力来弄清楚如何编写 declarative instead of imperative code

可以重构一点

// sync local state and props is a pain, better to avoid it
  //constructor(props) {
   //super(props);
    //const location = this.props.store.selectedLocation
   // this.state = {
      //LocationId: location.LocationId,
    //}
//}

 const location = this.props.store.selectedLocation;

render() {
    return (
        <div>
            <Modal>
                <Form>
                    <FormGroup>
                        <input
                            value={this.props.store.selectedLocation}
                            type="text"
                            name="Location"
                            id="Location"
                        />
                    </FormGroup>
                    <FormGroup>
                        {this.props.store.cationTypes.map((value) => (
                            <CustomInput
                                type="checkbox"
                                id={value.LocationTypeId}
                                key={value.LocationTypeId}
                                value={value.LocationTypeId}
                                defaultChecked={location.LocationTypes.includes(value.LocationTypeId)}
                                label={`${value.LocationTypeName}`}
                                className="mb-0"
                                onChange={this.handleCheckbox.bind(this)}
                            />}
                        ))
                    </FormGroup>
                </Form>
            </Modal>
        </div>
    );
}

【讨论】:

  • 那么我的方法应该是什么样的。我必须从商店中获取诸如名称/ID/已检查状态之类的复选框的值。它可以是 4 或 10 个复选框。在不打乱更新周期的情况下实现这一目标的最佳方法应该是什么。不过,感谢您的时间。非常感谢。
  • 更新了我的答案。
  • 我按照您的要求更新了代码并且它有效。非常感谢您的帮助,先生
猜你喜欢
  • 2019-03-13
  • 1970-01-01
  • 2022-01-21
  • 2020-09-11
  • 1970-01-01
  • 1970-01-01
  • 2021-09-23
  • 2018-07-19
  • 2017-07-06
相关资源
最近更新 更多