代码之家  ›  专栏  ›  技术社区  ›  JChao

reactjs-解决setState异步问题

  •  0
  • JChao  · 技术社区  · 6 年前

    我读过这篇文章: 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

    当我控制台.log new_apps ,一切都相应地工作,但是 console.log(this.state)

    3 回复  |  直到 6 年前
        1
  •  5
  •   Ricardo Costa    6 年前

    setState使您能够在设置状态后生成回调函数,以便获得真实状态

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

    this.setState({apps: new_apps}, () => console.log(this.state))
    
        2
  •  2
  •   rooch84    6 年前

        3
  •  2
  •   Jonas Wilms    6 年前

    实际上,不应该有两个状态保持相同的东西。相反,复选框应该是无状态的,状态应该只保留在应用程序列表中,然后向下传递:

    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>