gpbaculio
gpbaculio

Reputation: 5968

this.setState not working on componentWillMount()?

I want the state to be dependent on server data. I thought of using componentWillMount:

componentWillMount() {
    this.setState( async ({getPublicTodosLength}, props) => {
      const result =  await this.getPublicTodosLengthForPagination();
      console.log("result = ", result) // returns the length but not assigned on this.state.getPublicTodosLength
      return { getPublicTodosLength: result+getPublicTodosLength }
    });
  }

  getPublicTodosLengthForPagination = async () => { // get publicTodos length since we cannot get it declared on createPaginationContainer
        const getPublicTodosLengthQueryText = `
          query TodoListHomeQuery {# filename+Query
            viewer {
              publicTodos {
                edges {
                  node {
                    id
                  }
                }
              }
            }
          }`
    const getPublicTodosLengthQuery = { text: getPublicTodosLengthQueryText }
    const  result = await this.props.relay.environment._network.fetch(getPublicTodosLengthQuery, {})
    return await result.data.viewer.publicTodos.edges.length; 
  }

There is value but it's not assigned on my getPublicTodosLength state? I think I don't have to bind here since result returns the data I wanted to assign on getPublicTodosLength state

Upvotes: 0

Views: 2314

Answers (4)

gpbaculio
gpbaculio

Reputation: 5968

i decided to make componentWillMount async and it worked well.

this is the code:

componentWillMount = async () => {
    let result =  await this.getPublicTodosLengthForPagination();
    this.setState((prevState, props) => {
      return { 
        getPublicTodosLength: result 
      }
    });
  }

Upvotes: 0

Edgar Henriquez
Edgar Henriquez

Reputation: 1383

If you want your state to be dependent on server data you should use componentDidMount().

componentWillMount() is invoked immediately before mounting occurs. It is called before render(), therefore setting state synchronously in this method will not trigger a re-rendering. Avoid introducing any side-effects or subscriptions in this method. This is the only lifecycle hook called on server rendering. Generally, we recommend using the constructor() instead.

componentDidMount() is invoked immediately after a component is mounted. Initialization that requires DOM nodes should go here. If you need to load data from a remote endpoint, this is a good place to instantiate the network request. Setting state in this method will trigger a re-rendering.

From React Doc

Upvotes: 2

patotoma
patotoma

Reputation: 1119

Why not rather do something like this?

...
async componentWillMount() {
  const getPublicTodosLength = this.state.getPublicTodosLength;
  const result = await this.getPublicTodosLengthForPagination();
  this.setState({
    getPublicTodosLength: result+getPublicTodosLength,
  });
}
...

It's simpler and easier to read. I think the problem with the original code is with using async function inside setState(). In transpiled code there is another wrapper function created and then it probably loose context.

Upvotes: 1

trk
trk

Reputation: 2228

May be you could use:

Code snippet:

(async ({getPublicTodosLength}, props) => {
      const result =  await this.getPublicTodosLengthForPagination();
      console.log("result = ", result);
      return { getPublicTodosLength: result + getPublicTodosLength }
})).then((v)=> this.setState(v));

Please let me know if that works.

Upvotes: 0

Related Questions