6

I have the intention to perform a fetch to my rest api when ever the user updates an input bar. The problem I am having is that the componentDidUpdate method calls the action creator which dispatches the json to the reducer, in turn updating the state and calling componentDidUpdate again. Any ideas or best practices to end the endless cycle? Thanks!

Action Creator:

export const fetchFoods = (dispatch, searchText) => {
  return fetch(`/nutrition/${searchText}`)
    .then(res => res.json())
    .then(json => dispatch({type: 'RECEIVE_FOODS', json}))
}

Reducer:

const foods = (state = [], action) => {
  switch (action.type) {
    case 'RECEIVE_FOODS':
      return action.json
    default:
      return state
  }
}

React Container:

const FoodList = React.createClass({
  componentDidUpdate: function() {
    fetchFoods(this.props.dispatch, this.props.searchText)
  },
  componentWillMount: function() {
    fetchFoods(this.props.dispatch, this.props.searchText)
  },
  render: function() {
    ...
  }
})

export default connect(
  (state) => {
    return {searchText: state.searchText, foods: state.foods}
  }
)(FoodList)
2
  • You're updating immediately after updating, which forces an update. Commented Jul 13, 2016 at 19:11
  • You probably want to use mapDispatchToProps with connect to trigger an action when the input changes. Also explained here. Commented Jul 13, 2016 at 19:45

2 Answers 2

5

You should remove the fetchFoods function from the componentDidUpdate. Calling the function on an update will result in an infinite loop like you describe.

Once the component has mounted the first time and retrieved the original set of data, you should only call the action when it's explicitly required. If the user changes it, another function changes it, etc.

Sign up to request clarification or add additional context in comments.

Comments

1

Attach an onChange() handler to your input (or whatever you want to trigger an update), so that whenever input changes, it calls a function that explicitly dispatches that action.

https://jsfiddle.net/julianljk/69z2wepo/49105/

Function:

handleChange: function (e) {
    var myInput = e.target.value;
    this.setState({
        value: myInput
    });
    fetchFoods(this.props.dispatch, myInput) //sends it to the store, 
},        

Render:

render: function (){
    return( 
        <div>
            <input type="text" value={this.state.value} onChange={this.handleChange}/>
        </div>
)}    

Putting action dispatches in lifecycle methods can generally cause this sort of behavior.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.