Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEATURE] implement a getState method to get the sync state since setState is async. #12193

Closed
xialvjun opened this issue Feb 9, 2018 · 6 comments

Comments

@xialvjun
Copy link

xialvjun commented Feb 9, 2018

Do you want to request a feature or report a bug?

FEATURE REQUEST

What is the current behavior?

class MyComponent extends Component {
  state = { a: 1 }
  method1 = () => {
    this.setState({ a: 2 });
    this.method2();
  }
  method2 = () => {
    // It can not log 2 in the console.
    console.log(this.state.a);
  }
  // xxx...
}

What is the expected behavior?

class MyComponent extends Component {
  state = { a: 1 }
  method1 = () => {
    this.setState({ a: 2 });
    this.method2();
  }
  method2 = () => {
    // With the `getState` method, it should log 2 in the console.
    console.log(this.getState().a);
  }
  // xxx...
}
@TrySound
Copy link
Contributor

TrySound commented Feb 9, 2018

@xialvjun There's rfc which you may use to discuss
reactjs/rfcs#9

@xialvjun
Copy link
Author

xialvjun commented Feb 9, 2018

@TrySound My proposal is not totally the same as that rfc.

My proposal doesn't mutate any state. It's just get { ...this.state, ...{ a: 2 } }.

@gaearon
Copy link
Collaborator

gaearon commented Feb 9, 2018

Can you show a real-world use case where you feel this is necessary?

@milesj
Copy link
Contributor

milesj commented Feb 9, 2018

This is exactly what the callback is for. Are you not able to use it?

class MyComponent extends Component {
  state = { a: 1 }
  method1 = () => {
    this.setState({ a: 2 }, () => {
      this.method2();
    });
  }
  method2 = () => {
    // Is log 2 in the console.
    console.log(this.state.a);
  }
  // xxx...
}

@xialvjun
Copy link
Author

Well, it indeed can use the callback to ensure this.method2 be executed after rendered.
In fact I have forgotten why I want this API.
I just remember once upon a time I was confused about does the component have rendered and the state have merged if the event occurred too fast, like onScroll, I can not totally rely on this.state, so sometimes I attach some state just on this, like this.a=xxx;...

...
well, sorry, maybe this API is not that necessary.

@xialvjun
Copy link
Author

xialvjun commented Mar 8, 2018

use case is just like this, What is the difference between passing an object or a function in setState?

incrementCount() {
  this.setState((prevState) => {
    // Important: read `prevState` instead of `this.state` when updating.
    return {count: prevState.count + 1}
  });
}

handleSomething() {
  // Let's say `this.state.count` starts at 0.
  this.incrementCount();
  this.incrementCount();
  this.incrementCount();

  // If you read `this.state.count` now, it would still be 0.
  // But when React re-renders the component, it will be 3.
}

Yeah, setState with a function is OK. Then how about this?

checkAndDoSomething() {
  if (this.getState().count > 5) {
    doSomething();
  }
}
incrementCount() {
  this.setState((prevState) => ({count: prevState.count + 1}))
}
incrementManyTimes(time) {
  for (let i = 0; index < time; i++) {
    this.incrementCount();
  }
  this.checkAndDoSomething();
}

And in fact, we can change incrementCount to:

incrementCount() {
  this.setState({count: this.getState().count + 1})
}

Why should we use getState rather than setState with function as argument?

  1. it has much more consistency: getState <-> setState;
  2. it has purer purpose: getState is just to get state, but setState with function as argument is to get state and use that state to set state;

@gaearon

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants