reactjs-解决setState异步问题

时间:2018-09-07 15:41:39

标签: javascript reactjs

我已经阅读了这篇文章:React setState not Updating Immediately

并意识到setState是异步的,可能需要第二个arg作为函数来处理新状态。

现在我有一个复选框

class CheckBox extends Component {
    constructor() {
        super();
        this.state = {
            isChecked: false,
            checkedList: []
        };
        this.handleChecked = this.handleChecked.bind(this);
    }

    handleChecked () {
        this.setState({isChecked: !this.state.isChecked}, this.props.handler(this.props.txt));
    }

    render () {
        return (
            <div>
                <input type="checkbox" onChange={this.handleChecked} />
                {`   ${this.props.txt}`}
            </div>
            )
    }
}

并且正被另一个应用程序使用

class AppList extends Component {
    constructor() {
        super();
        this.state = {
            checked: [],
            apps: []
        };
        this.handleChecked = this.handleChecked.bind(this);
        this.handleDeleteKey = this.handleDeleteKey.bind(this);
    }
    handleChecked(client_id) {
        if (!this.state.checked.includes(client_id)) {
            let new_apps = this.state.apps;
            if (new_apps.includes(client_id)) {
                new_apps = new_apps.filter(m => {
                    return (m !== client_id);
                });
            } else {
                new_apps.push(client_id);
            }
            console.log('new apps', new_apps);
            this.setState({apps: new_apps});
            // this.setState({checked: [...checked_key, client_id]});
            console.log(this.state);
        }
    }
    render () {
        const apps = this.props.apps.map((app) =>
            <CheckBox key={app.client_id} txt={app.client_id} handler={this.handleChecked}/>
        );

        return (
            <div>
                <h4>Client Key List:</h4>
                {this.props.apps.length > 0 ? <ul>{apps}</ul> : <p>No Key</p>}
            </div> 
        );
    }


}

因此,每次复选框状态更改时,我都会更新this.state.apps中的AppList

当我console.log new_apps时,一切都可以正常工作,但是console.log(this.state)显示状态没有立即更新,这是可以预期的。我需要知道的是,当我需要执行进一步的操作(例如注册所有这些选定的字符串或其他内容)时,如何确保状态被更新

3 个答案:

答案 0 :(得分:3)

setState使您可以在设置状态后创建回调函数,以便获得真实状态

this.setState({stateYouWant}, () => console.log(this.state.stateYouWant))

在您的情况下:

this.setState({apps: new_apps}, () => console.log(this.state))

答案 1 :(得分:2)

其他人对setState回调有正确的答案,但我也建议将CheckBox设置为无状态,并从MyApp传递isChecked作为道具。这样,您只需保留一项是否已检查项目的记录,而无需在两者之间进行同步。

答案 2 :(得分:2)

实际上,不应有两个州保持同一事物。取而代之的是,复选框应为无状态,状态应仅保留在AppList中,然后向下传递:

const CheckBox = ({ text, checked, onChange }) => 
        (<span><input type="checkbox" checked={checked} onChange={() => onChange(text)} />{text}</span>);
        
class AppList extends React.Component {
  constructor() {
    super();
    this.state = { 
      apps: [
        {name: "One", checked: false },
        { name: "Two", checked: false }
      ], 
    };
  }
  
  onChange(app) {
    this.setState(
      previous => ({ 
         apps: previous.apps.map(({ name, checked }) => ({ name, checked: checked !== (name === app) })),
      }),
      () => console.log(this.state)
    );
  }
  
  render() {
    return <div>
     {this.state.apps.map(({ name, checked }) => (<CheckBox text={name} checked={checked} onChange={this.onChange.bind(this)} />))}
    </div>;
  }
}

ReactDOM.render(<AppList />, document.body);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>