Is it OK to make a REST API request from within a Redux reducer?

Der*_*ler 9 reactjs react-redux

I have a React component named ItemList which loads a list of items from an API server and then renders them as a list of Item components.

Each Item has a delete button. When the button is clicked, I want to send a request to the API server to delete the item, then re-render the ItemList.

One way I can think of to make that work is to move both API queries into reducers, and then dispatch actions whenever I want to a) get all items; and b) delete an item. Upon successful completion of those API operations, the reducer will update the store and the ItemList will re-render.

Is that a reasonable approach, or is it a bad idea to put API calls inside of reducers?

Here's a simplified version of the the code I have so far. It doesn't yet use Redux. I want to make sure my approach is sound before implementing Redux, hence this Stack Overflow question.

ItemList.js

class ItemList extends Component {

  constructor(props) {
    super(props);
    this.state = {
      items: []
    };
    this.componentDidMount = this.componentDidMount.bind(this);
  }

  componentDidMount() {
    const url = 'https://api.example.com/api/v1.0/item';
    fetch(url, {
      method: "get"
    })
    .then(res => res.json())
    .then(response => {
      this.setState({items: response.data});
    });
  }

  render() {
    <div>
      {this.state.items.map((item, index) => (
        <Item key={item.id} item={item} />
      ))}
    </div>
  }
}
Run Code Online (Sandbox Code Playgroud)

Item.js

class Item extends Component {

  deleteClicked() {
    /** 
     *  Is it ok to dispatch a "delete item" action 
     *  from here and then make the actual API call 
     *  in a reducer?
     */
  }

  render() {
    <div>
      <h2>{item.title}</h2>
      <a onClick={this.deleteClicked}>delete item</a>
    </div>
  }
}
Run Code Online (Sandbox Code Playgroud)

Fyo*_*dor 13

你几乎完成了你的任务。为了使您的解决方案完美,请使用动作创建者进行异步调用并在完成时分派动作。Reducer 应该是纯同步功能

例如ItemList组件可以使用这样的动作创建器来提取项目

const ExtractItemsAction = () => (dispatch) => {
    dispatch ({type: ITEMS_REQUESTED});
    const url = 'https://api.example.com/api/v1.0/item';
    fetch(url, {
        method: "get"
    })
    .then(res => res.json())
    .then(response => {
        dispatch({type: ITEMS_RECEIVED, items: response.data});
    });
}
Run Code Online (Sandbox Code Playgroud)

并且减速器将保持纯净

function reducer (state = initalState, action)
{
    switch (action.type) {
        case ITEMS_REQUESTED:
            return { ...state, itemsRequested: true }
        case ITEMS_RECEIVED:
            return { ...state, itemsRequested: false, items: action.items }
        default
            return state;
    }
}
Run Code Online (Sandbox Code Playgroud)

并且不要忘记您的组件连接到 Redux,并在创建 store 时使用Redux-thunk作为中间件。