Actions must be plain Objects in React/Redux?

2019-02-21 03:18发布

问题:

the problem I'm running into is Actions must be plain objects when passing data through my action creators. Basically I'm trying to capture user input through the click of a button, and based on what button (view) is clicked the event.target.innerHTML is passed to the action creator fetchDataAsync(view) which then performs a GET request via axios and dispatches based on what view was selected.

I'm still new with Redux, though, and I'm unsure of what I'm doing wrong here. I've seen an async action performed inside an action creator before...

Component connected with Redux:

class ViewSelector extends Component {
  selectView(event) {
    this.props.fetchDataAsync(event.target.innerHTML);
  }

  render() {
    return (
      <nav>
        <button onClick={this.selectView.bind(this)}>VIEW ALL</button>
        <button onClick={this.selectView.bind(this)}>VIEW LAST WEEK</button>
        <button onClick={this.selectView.bind(this)}>VIEW LAST MONTH</button>
      </nav>
    );
  }
}

function mapStateToProps(state) {
  return {
    view: state.view
  };
}

export default connect(mapStateToProps, actions)(ViewSelector);

Action creator for dispatching based on event.target.innerHTML:

export function fetchDataAsync(view) {
  return dispatch => {
    dispatch(fetchData());

    axios.get(DATA_URL)
    .then(res => {
      dispatch(fetchDataSuccess(res.data));
      if (view == 'VIEW LAST WEEK') {
        dispatch(lastWeekData(res.data));
      } else if (view == 'VIEW LAST MONTH') {
        dispatch(lastMonthData(res.data));
      }
    }).catch(err => {
      dispatch(fetchDataFailure(err));
    });
  };

}

Any advice is appreciated. Or if you believe there's a more effective way of capturing that user input and passing it to an action creator...I'd be curious to hear more!

回答1:

You need to install redux-thunk to use async action. And then create your store like this

import thunk from 'redux-thunk';
const store = createStore(YOURREDUCER, applyMiddleware(thunk));


回答2:

The general idea that you have above is correct. In the React component, you want to isolate the information that is relevant for the async function and call the action-creator with that information. The action creator can make an XHR call, and then dispatch actions accordingly.

(I am assuming that you have middleware installed, otherwise do look at something like redux-thunk to get started. The middleware helps connect the dots in this case, making sure async actions and results are dispatched appropriately).

Without knowing too much about the lastWeekData, lastMonthData, etc, I would only suggest possibly simplifying the 'then' part of the call. If there is any special logic, it conventionally belongs in the reducer.