简体   繁体   中英

How to Assign react redux state api get data using axios

i used react 16+ and redux get jsonplaceholder fake data to assign posts state but not working. can't assign the state. how can i assign json values into state using concat method. i check lifecycle methods also but can't get the answer.

Reducer

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 reducers must be pure functions, it means they should not contain any side effects like calling api.

You need to call api in action creators using redux-thunk package.

Codesandbox

An example action creator:

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
    }
  };
};

And reducer file:

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;
  }
}

In store we use redux-thunk like this:

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;

Posts component:

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);

Index.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
);

Do api call in action and return promise, use redux-thunk and redux-promise-middleware:

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

Then in reducer will have to handle two results: MY_API_CALL_FULFILLED and MY_API_CALL_REJECTED

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM