【问题标题】:React this.state not updating correctly when called within if else statement with use of immutability-helper使用 immutability-helper 在 if else 语句中调用时反应 this.state 未正确更新
【发布时间】:2018-07-31 20:45:12
【问题描述】:

我正在尝试创建一个简单的水平标签栏组件。如果用户单击选项卡,则容器会执行一些逻辑。

通过this.state在容器中跟踪标签状态。容器的道具之一是一个名为“选项”的数组。长度决定了标签栏中的标签数量。

constructor(props){
        super(props)

        var arrayWithTabs = []
        var isSelected;

        this.props.options.map((option, i) => {

            if (option == this.props.selected){
                isSelected = true
            } else {
                isSelected = false 
            }
            var tabObject = {
                optionName: option,
                isSelected: isSelected
            }
            arrayWithTabs.push(tabObject)

        })

        this.state = {
            options: arrayWithTabs,
        }

每当用户点击时,handleClick 就会被触发:

     updateState = (index,isSelected) => {
        this.setState((prevState) => {
            return update(prevState.options,{
                [index]: {
                    isSelected:{$set: isSelected}
                }
            })
        })
    }

    handleClick(e) {
        this.state.options.map((option, i) => {

            const isSelected = option.optionName == e.target.id;

            this.updateState(i, isSelected);
        })     
      }


    componentDidUpdate(){
        console.log(this.state.options)
    }

为了处理我读到的 setState 的异步行为,你不应该直接从 this.state 中读取,而是在 setState 中创建一个函数来接收 prevState。

但是,当单击任何选项卡时,componetDidUpdate() 会返回以下内容:

[{optionName: "Tab1", isSelected: false}
{optionName: "Tab2", isSelected: false}]

【问题讨论】:

    标签: javascript reactjs typescript


    【解决方案1】:

    首先map函数返回一个数组。如果你不想从内部返回任何东西,你应该使用 forEach。

    其次,在构造函数中你应该避免使用 this.props,因为你已经得到了 props。使用那个。

    最后你可以在handleClick方法中做如下操作

    handleClick(e) {
        const options = this.state.options.map((option, i) => {
    
            var isSelected = option.optionName === e.target.id;
            return {optionName: option.optionName, isSelected: isSelected}
        });
        this.setState({options})
      }
    

    也可以如下修改构造函数

    constructor(props){
        super(props)
    
        var options = props.options.map((option) => {
    
            var isSelected = (option == this.props.selected)
            return {
                optionName: option,
                isSelected: isSelected
            }
    
        })
    
        this.state = {
            options: options
        }
    }
    

    【讨论】:

    • 谢谢@Parth Pandya。我使用了您的代码,它现在按预期工作!但是,我不确定为什么我自己的 handleClick 和 updateState 不起作用。如果您能指出我应该在那里进行的确切错误/更正以便它与 immutability-helper 更新功能一起使用,那就太好了。所以下次我可以在某个地方使用它。
    • 问题是 updateState 为选项数组中的每个选项调用。在 updateState 中,setState 方法采用先前的状态并仅更改给定索引的值。现在假设它确实改变了你需要的状态。但是 this.setState 是一个异步函数,这意味着它不能保证在下一次迭代中它会获得更新的状态。因此,在 handleClick 中 isSelected 为 false 的选项,updateState 可能会在构造函数中采用具有初始化值的状态,并将给定索引设置为 false。
    【解决方案2】:

    您可以使用回调来确保setState 已完成,例如:

    addNewTabs(newOptions) {
        this.setState({ options:newOptions }, () => {
             console.log("Finished updating state:", this.state);
             // Do something with the updated state here...
        });
    }
    

    尝试将您的代码重组为以下内容:

    handleClick(e) {
    
      var updatedState;
    
      this.state.options.map((option, i) => {
        const isSelected = option.optionName == e.target.id;
        updatedState = update(this.state.options, {
          [i]: {$set:{optionName: option.optionName, isSelected:isSelected}}
        });  
      });
    
      this.setState({ options:updatedState }, () => {
        console.log(updatedState);
      });
    }
    

    【讨论】:

    • 感谢重组建议。我在 this.setState 上阅读了更多内容,显然在更新状态时您不能直接从 this.state 中读取。相反,您应该在 this.setState 中使用 prevState 中的函数。然而仍然没有成功。我已经更新了帖子..
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-28
    • 1970-01-01
    • 1970-01-01
    • 2021-02-20
    • 2020-07-06
    • 2021-11-29
    相关资源
    最近更新 更多