Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to update store state in react-redux?

I'm working on a component in React (with Redux) that has the requirements to:

  1. Retreive data from an API endpoint.
  2. Display that data, with one field being editable.
  3. If the editable field is edited, it has to update the rest of the fields and send them to a different endpoint.

I'm having trouble grasping how exactly I should implement the editing using the Redux metodology.

Here is a simplified component:

class MyComponent extends Component {
  constructor(...args) {
    super(...args);
    this.props.dispatch(getDataFromEndpoint());
  }
  editField(e) {
    this.props.dispatch(editFieldAction(e.target.value));
  }
  render() {
    return (
      <div>
        <input type="text" defaultValue={this.props.data.editableField} onChange={this.editField} />
        {
          this.props.data.uneditable.map(x => {
            return (
              <span>{x}</span>
            );
          })
        }
      </div>
      );
  }
}

const mapProps = state => {
  const { data } = state.endpointData;
  return { data };
}

export default connect(mapProps)(MyComponent);

Note that I've written this component as an example, it might have errors, but you should get the point. Whenever this.editField is called, it should update every value in this.props.data.uneditable.

What is the correct way to do this?

like image 765
Gregor Menih Avatar asked Jul 28 '16 17:07

Gregor Menih


1 Answers

In a sense these questions all boil down to: How do I wire up my component(s) to read from (and write to) Redux state. This is essentially the purpose of redux-react's connect function (which you have in the bottom of your example). You use the first parameter, mapStateToProps, to be able to read from state. You use the second parameter (that you don't have yet) - mapDispatchToProps - to provide the means to write to it. Dispatching an action is how you update Redux state.

You can simply use this.props.dispatch, but it is more idiomatic to use mapDispatchToProps, which simply provides an object where each property is a function which calls dispatch with the appropriate action creator. You might accept as a parameter for example the data which you are looking to update your store with.

What ends up happening is in your component when you want to update the state (say from an input), you use the methods you wired up with mapDispatchToProps to dispatch an action with the relevant data (the updated input value), and then write a reducer which responds to the action and updates the relevant part of your store. Redux will then trigger a re-render in your component and it will pull the updated data from the store.

Async actions are handled a bit differently of course (which is what your API calls will be), because they typically have several changes to state being spread out over time. Usually something like:

  • Start the API request. (Dispatch an action to..) Set a flag somewhere in your state indicating the API request is 'in transit'.
  • Receive the response. (Dispatch again to..) Set a flag somewhere saying the request is finished, and if it was successful, store your response data somewhere. If it was an error, store the error (or just the fact there was an error).

I would recommend redux-thunk for this purpose, since at least for me it is the easiest to understand and work with out of all the various libraries and methods to handle async with redux. Instead of dispatching an object which contains the data describing the action, you instead dispatch a function, which means you can write any kind of logic you would like, allowing you to dispatch several times for example. This makes it easy to do the steps outlined above.. simply have a function which calls your API, and in the callback (or .then() method) you dispatch an action with the result.

like image 89
John Avatar answered Nov 15 '22 02:11

John