setState回调不按预期工作

问题描述:

我有一个工作的应用程序,我只是试图设置状态为loading: true,而我的应用程序进行提交调用,所以我可以显示加载屏幕。因为我想确保在之前设置状态进行加载调用,所以我使用回调。但是我没有看到我的加载更新代码如下:setState回调不按预期工作

submitSecurityAnswer =() => { 
    const { submit, handleError, navigate } = this.props; 
    const { answer } = this.state; 

    this.setState({ loading: true },() => { 
     console.log('setState', this.state) 
     try { 
     submit({ answer, ...this.props }).then(({ errors, status }) => { 
      this.setState({ answer: '' }); 
      if (status && status === 200) { 
      navigate(); 
      } else if (status === 401) { 
      this.setState({ showError: true }); 
      } else { 
      handleError(errors[0]); 
      } 
     }); 
     } catch (err) { 
     console.log(err); 
     } 
    }); 

    this.setState({ loading: false }); 
    }; 

当我检查我的控制台日志我看到,国家还没有更新,加载仍然是假的。

我在这里错过了什么?

+0

如果我明白你正在尝试做正确的'this.setState({装:假})'应该是正确的或之前'navigate();' – bennygenel

+0

'后面实际上如果你改变'this.setState({answer:''});'到'this。setState({answer:'',loading:false});'它应该也工作 – bennygenel

+0

是啊,我试图'this.setState({loading:false})''submit()' – Turnipdabeets

发生这种情况,因为你在你的函数结束通话this.setState({ loading: false });。您可以同时设置loading: trueloading: false。当你的回调正在调用时,最后一个setState函数也会将状态值更改为false。

您应该设置负载状态虚假收到请求后:

submitSecurityAnswer =() => { 
    const { submit, handleError, navigate } = this.props; 
    const { answer } = this.state; 

    this.setState({ loading: true },() => { 
    console.log('setState', this.state) 
    try { 
     submit({ answer, ...this.props }).then(({ errors, status }) => { 
     this.setState({ answer: '' }); 
     if (status && status === 200) { 
      navigate(); 
     } else if (status === 401) { 
      this.setState({ showError: true, loading: false }); 
     } else { 
      handleError(errors[0]); 
     } 
     }); 
    } catch (err) { 
     console.log(err); 
    } 
    }); 
}; 

这是因为您在异步操作完成之前将loading设置为false
只需在callback内移动this.setState({ loading: false });;

编辑
作为随访到您的评论:

我试图消除这一点,但看到了同样的结果

我没说要删除它只是移动它内部回调setstate
发生了什么是您将它设置为true,然后false在相同的调用堆栈迭代,而不是等待异步操作完成。

考虑这个情景,这是类似代码:
在这个例子中我设置loading回假异步操作(setTimeout)之前完成,因此我只是覆盖了以前的状态,而无需等待。

class App extends React.Component { 
 
    constructor(props) { 
 
    super(props); 
 
    this.state = { 
 
     loading: false, 
 
     message: '' 
 
    }; 
 
    } 
 

 
    componentDidMount() { 
 
    this.setState({ loading: true },() => { 
 
     console.log(this.state); 
 
     setTimeout(() => { 
 
     this.setState({ 
 
      message: 'we have data' 
 
     }); 
 
     console.log(this.state); 
 
     }, 500); 
 
    }); 
 

 
    this.setState({ loading: false }); 
 
    } 
 

 
    render() { 
 
    const {message, loading} = this.state; 
 
    return (
 
     <div> 
 
     {loading ? <div>Loading...</div> : <div>{message}</div>} 
 
     </div> 
 
    ); 
 
    } 
 
} 
 

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

的修复将是移动回调内的下一个状态改变:
在这个例子中我移动回调内的线this.setState({ loading: false });异步操作已经完成并且该固定不需要的行为之后。

class App extends React.Component { 
 
    constructor(props) { 
 
    super(props); 
 
    this.state = { 
 
     loading: false, 
 
     message: '' 
 
    }; 
 
    } 
 

 
    componentDidMount() { 
 
    this.setState({ loading: true },() => { 
 
     console.log(this.state); 
 
     setTimeout(() => { 
 
     this.setState({ 
 
      message: 'we have data' 
 
     }); 
 
     this.setState({ loading: false }); 
 
     }, 500); 
 
    }); 
 

 
    } 
 

 
    render() { 
 
    const {message, loading} = this.state; 
 
    return (
 
     <div> 
 
     {loading ? <div>loading...</div> : <div>{message}</div>} 
 
     </div> 
 
    ); 
 
    } 
 
} 
 

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

+0

我试图删除,但看到了相同的结果。 – Turnipdabeets

+0

我没有说删除,我说移动它的回调函数内。看我的例子 –