JohnKochJR
JohnKochJR

Reputation: 133

Setting state value in react native

Here is what I am trying to do and examples I have found don't seem to set the value either. So I am sure it is something simple I am over-looking.

setViewedSubmission(subId: string) {
    logger.log("pre:", this.state.position.candidates.find((c)=> {
        return c.submissionId == subId
    }).viewedSubmission) //returns original value

    this.state.position.candidates.find((c)=> {
        return c.submissionId == subId
    }).viewedSubmission = true //expect the value to update
    this.forceUpdate()

    logger.log("post:", this.state.position.candidates.find((c)=> {
        return c.submissionId == subId
    }).viewedSubmission) //returns original value still
}

This is what I actually started with but also doesn't work: Based on the responses, this is closer to what I should be doing but still doesn't. What is the issue here?

 let pos = Object.assign({}, this.state.position)
    pos.candidates.find((c) => {
        return c.submissionId == subId
    }).viewedSubmission = true;

    this.setState({ position: pos })

Upvotes: 0

Views: 2929

Answers (3)

mcssym
mcssym

Reputation: 944

The only way to update the state and get the screen re-rendered is to use the setState method. Here a look:

let candidates = this.state.position.candidates;
candidates = candidates.map(candidate => {
    if(candidate.submissionId === subId) candidate.viewedSubmission = true;
    return candidate;
});
this.setState(prevState => ({
    position: {
        ...prevState.position,
        candidates
    }
}));

Upvotes: 1

Filipe
Filipe

Reputation: 884

You can't alter state directly. It is immutable (If you plan on working with React, you should read more about that). When you say this.state.value = 1, it won't update. Instead, you should do this.setState({ value: 1 }). And, if there are more itens in state, you should do this.setState(p => ({ ...p, value: 1 }), since when you update state, you must return the entire new state object.

Upvotes: 0

Daniel B. Chapman
Daniel B. Chapman

Reputation: 4687

I think you're looking at this backwards. React is basically a state machine which means the UI reflects the current status of the state.

Without delving too deep into your code you probably want to structure things something similar to the following:

class Demo extends React.Component {
  constructor(props){
    super(props)
    this.state = {
      viewed: false,
    }
  }
  someBusinessLogic(viewed) {
    this.setState({
      ...this.state,
      viewed: viewed,
    })
  }

  render() { 
    const { viewed } = this.state
    if (viewed ) {
     return <div>VIEWED</dive>
    } else {
     return <div>UNVIEWED</div>
    }
  }
}

...and somewhere else

...//this is terrible code, just an example of using the business logic
  <Demo viewed='true' ref={r => this.demo1 = r} />
  <Demo viewed='false'/>

  <button onClick={e => { this.demo1.someBusinessLogic('viewed') }}>Set Viewed = 'viewed'</button>
...

Structuring the component this way means that you reflect upon the state rather than trying to manage when updates occur. setState(newState) will re-render if the state is different.

My guess is that the internal state of your component is the same.

If I misread your question and you are not seeing updates passed to the component make sure you are using the key and that it is updating or override shouldComponentUpdate which is where forceUpdate starts to be useful.

Hopefully this helps, you might consider providing more details about your implementation so the community can be more specific.

Upvotes: 1

Related Questions