javascript - setState callback not working as expected - Stack Overflow

I have a working app and am just trying to set the state to loading: true while my app makes a submissi

I have a working app and am just trying to set the state to loading: true while my app makes a submission call so I can show a loading screen. Because I want to make sure I set the state before making the loading call, I use a callback. However I'm not seeing my loading update with the code below:

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 });
  };

When I check my console log I see that the state has not updated and loading is still false.

What am I missing here?

I have a working app and am just trying to set the state to loading: true while my app makes a submission call so I can show a loading screen. Because I want to make sure I set the state before making the loading call, I use a callback. However I'm not seeing my loading update with the code below:

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 });
  };

When I check my console log I see that the state has not updated and loading is still false.

What am I missing here?

Share Improve this question asked Oct 11, 2017 at 18:13 TurnipdabeetsTurnipdabeets 6,0159 gold badges45 silver badges65 bronze badges 5
  • If I understood what you are trying to do correctly your this.setState({loading:false}) should be right before or after navigate(); – bennygenel Commented Oct 11, 2017 at 18:18
  • actually if you change this.setState({ answer: '' }); to this.setState({ answer: '', loading:false }); it should work too – bennygenel Commented Oct 11, 2017 at 18:18
  • yea, I'm trying to this.setState({loading:false}) before the submit() – Turnipdabeets Commented Oct 11, 2017 at 18:19
  • then put it before the submit() function – bennygenel Commented Oct 11, 2017 at 18:19
  • You are calling this.setState({ loading: true }) and this.setState({ loading: false }) at the same time. The latter call kind of overrides the first one. – Felix Kling Commented Oct 11, 2017 at 18:23
Add a ment  | 

2 Answers 2

Reset to default 4

This is happening, because you are calling this.setState({ loading: false }); in the end of your function.

You are setting loading: true and loading: false at the same time. When you your callback is invoking, the last setState function is also changed state value to false.

You should set loading state to false after request was received:

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);
    }
  });
};

That because you are setting loading to false before the async operation has pleted.
Just move this.setState({ loading: false }); inside the callback;

Edit
As a followup to your ment:

I tried removing that but saw the same results

I didn't say to remove it just move it inside the callback of setstate.
What happens is that you are setting it to true then false at the same call stack iteration and not waiting for the async operation to plete.

Consider this scenario which is similar to your code :
In this example i set the loading back to false before the async operation (setTimeout) is finished, hence i'm just overriding the previous state without waiting.

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

  ponentDidMount() {
    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./ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

The fix will be to move the next state change inside the callback:
In this example i moved the line this.setState({ loading: false }); inside the callback after the async operation has pleted and this fixed the unwanted behavior.

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

  ponentDidMount() {
    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./ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1743730499a4497352.html

相关推荐

  • javascript - setState callback not working as expected - Stack Overflow

    I have a working app and am just trying to set the state to loading: true while my app makes a submissi

    7天前
    10

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信