【问题标题】:How to Assign react redux state api get data using axios如何使用axios分配react redux state api获取数据
【发布时间】:2019-12-04 00:13:45
【问题描述】:

我使用 react 16+ 和 redux 获取 jsonplaceholder 假数据来分配帖子状态但不工作。无法分配状态。如何使用 concat 方法将 json 值分配给状态。我也检查了生命周期方法,但无法得到答案。

减速器

import * as actiontypes from './actions';
import axios from 'axios';

const initalstate = {
    counter: 0,
    posts: []
};

const reducer = (state = initalstate, action ) => {
    switch (action.type) {
        case actiontypes.actionFetchPost:
            axios.get('https://jsonplaceholder.typicode.com/posts')
                .then(res => {
                    return {
                        ...state,
                        posts: state.posts.concat(res.data)
                    }
                });
            break;
        default :
            return state;
    }
};

export default reducer;

【问题讨论】:

  • 使用 redux-thunkredux-saga 并在您的操作中以异步方式进行获取,而不是在您的减速器中。
  • From the docs: 在 reducer 中你应该永远做的事情:改变它的参数;执行 API 调用和路由转换等副作用;调用非纯函数,例如Date.now()Math.random()。除此之外,您将在您的承诺的 .then() 处理程序中返回新状态。它根本不会更新您的商店。另请参阅 Async Actions 了解使用 redux 处理异步操作的方法。

标签: javascript reactjs redux


【解决方案1】:

Redux reducer 必须是纯函数,这意味着它们不应包含任何副作用,例如调用 api。

您需要使用redux-thunk 包在动作创建者中调用api。

Codesandbox

动作创建者示例:

import {
  FETCH_POSTS_STARTED,
  FETCH_POSTS_FAILURE,
  FETCH_POSTS_SUCCESS
} from "./actionTypes";
import axios from "axios";

export const fetchPosts = () => {
  return dispatch => {
    dispatch(fetchPostsStarted());

    axios
      .get("https://jsonplaceholder.typicode.com/posts")
      .then(res => {
        dispatch(fetchPostsSuccess(res.data));
      })
      .catch(err => {
        dispatch(fetchPostsFailed(err.message));
      });
  };
};

const fetchPostsStarted = () => {
  return {
    type: FETCH_POSTS_STARTED,
    payload: {
      isLoading: true
    }
  };
};

const fetchPostsSuccess = posts => {
  return {
    type: FETCH_POSTS_SUCCESS,
    payload: {
      posts
    }
  };
};

const fetchPostsFailed = error => {
  return {
    type: FETCH_POSTS_FAILURE,
    payload: {
      error
    }
  };
};

还有reducer文件:

import {
  FETCH_POSTS_STARTED,
  FETCH_POSTS_SUCCESS,
  FETCH_POSTS_FAILURE
} from "../actions/actionTypes";

const initialState = {
  posts: [],
  loading: false,
  error: null
};

export default function(state = initialState, action) {
  switch (action.type) {

    case FETCH_POSTS_STARTED:
      return {
        ...state,
        loading: true
      };
    case FETCH_POSTS_SUCCESS:
      return {
        ...state,
        loading: false,
        error: null,
        posts: action.payload.posts
      };
    case FETCH_POSTS_FAILURE:
      return {
        ...state,
        loading: false,
        error: action.payload.error
      };
    default:
      return state;
  }
}

在商店中,我们像这样使用 redux-thunk:

import { createStore, compose, applyMiddleware, combineReducers } from "redux";
import reduxThunk from "redux-thunk";
import postsReducers from "./reducers/postsReducers";

const rootReducer = combineReducers({
  posts: postsReducers
});

const store = createStore(rootReducer,  compose(applyMiddleware(reduxThunk)));

export default store;

帖子组件:

import React, { Component } from "react";
import { connect } from "react-redux";
import { fetchPosts } from "./store/actions/postsActions";

class Posts extends Component {
  componentDidMount() {
    this.props.fetchPosts();
  }

  render() {

    const { posts, loading, error } = this.props;

    return (
      <div>
        {loading && <div>LOADING...</div>}
        {error && <div>{error}</div>}
        <ul>
          {posts.map(post => (
            <li key={post.id}>{post.title}</li>
          ))}
        </ul>
      </div>
    );
  }
}

const mapStateToProps = state => {
  const { posts, loading, error } = state.posts;
  return {
    posts,
    loading,
    error
  };
};

export default connect(
  mapStateToProps,
  {
    fetchPosts
  }
)(Posts);

索引.js

import ReactDOM from "react-dom";
import store from "./store/store";
import { Provider } from "react-redux";
import Posts from "./Posts";

function App() {
  return (
    <div className="App">
      <Posts />
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  rootElement
);

【讨论】:

    【解决方案2】:

    做api调用并返回promise,使用redux-thunk和redux-promise-middleware:

    export const myApiCall = (args1, arg2) => async (dispatch, getState) => {
      const payload = fetch({ ...config });
      return dispatch({ type: 'MY_API_CALL', payload });
    }
    

    那么在reducer中将不得不处理两个结果: MY_API_CALL_FULFILLED 和 MY_API_CALL_REJECTED

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-06-15
      • 2018-11-14
      • 2020-05-02
      • 1970-01-01
      • 2020-09-10
      • 2018-01-31
      • 2020-07-25
      • 1970-01-01
      相关资源
      最近更新 更多