使用Redux在Axios调用后更新React组件状态

时间:2019-07-19 14:37:29

标签: javascript reactjs redux

我正在努力学习React和Redux。作为其中的一部分,我正在创建一个简单的应用程序,该应用程序从REST API中检索项目列表。要查询此REST API,我正在使用Axios。目前,我不了解如何实际更新商店中的状态。 Redux的例子令人困惑。

这时,我的应用程序具有以下内容:

/my-app
  /actions
    items.js
  /components
    items.js
  App.css
  App.js
  index.css
  index.js
  store.js

/my-app/actions/items.js

import axios from 'axios';

export GET_ITEMS = 'GET_ITEMS';

export const getItems = (count) => {
  axios.get('https://my-app.com/items')
    .then(function(response) {
      console.log(response.results);
      // need to set "response.results" to the value in the store
    }
};

/components/items.js

import React from 'react';

import { getItems } from '../actions/items';

class Items extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      items: []
    }
  }

  onButtonClick = () => {
    getItems(5);
  }

  render() {
    return {
      <div>
        <button type="button" onClick={this.onButtonClick}>Load Items</button>
        <br />

        {this.state.items.map((item) => {
          <div>{item.name}</div>
        ))}
      </div>
    }
  }
}

App.js

import React from 'react';

import Items from './components/items';

function App() {
  return {
    <div>
      <Items></Items>
    </div>
  };
}

export default App;

/store.js

import { createStore } from 'redux';

import { GET_ITEMS } from './actions/items';

let initialState = {
  items: [
    {
      id:1,
      name:'Item A',
      description: 'This is a pre-populated item for testing purposes.'
    }
  ]
}

function itemsReducer(state, action) {
  switch (action.type) {
    case GET_ITEMS:
      break;
    default:
      return state;
  }
}

let store = createStore(itemsReducer, initialState);
export default store;

index.js

import React from 'react';
import ReactDOM from 'react-dom';

import { Provider } from 'react-redux';
import store from './store';

import App from './App';

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

运行此命令时,我看到带有按钮的屏幕。我可以单击该按钮,但是,我看不到屏幕上显示的项目。如果在控制台窗口中查看,则可以看到通过console.log语句打印的项目。

如何获取从REST API返回的项目,以及a)在store中设置这些项目,以及b)使用组件中的存储项目?

非常感谢您的帮助! Redux一直是一个挑战。

1 个答案:

答案 0 :(得分:0)

为了简单起见,我将保留此文件夹结构

/my-app
  /API
    index.js
  /state
     action-types.js
    /actions
       items.js
    /reducers
       items.js
  /components
    /items
       ItemComponent.js

我喜欢将API与状态分开,以更好地分离关注点/控制

API / index.js

import axios from 'axios';

const BASE_URL = 'https://my-app.com/items';

export const getItems = () => {
  axios
    .get(`${BASE_URL}/items`)
    .then(response => response.data)
    .catch(error => error);
};

原因,我喜欢这种方法

  • 这允许调用getItems API端点而无需调用getItems操作和状态更新
  • 如果您决定使用任何其他API库来代替axios,则无需修改所有操作文件

action-types.js

  export const GET_ITEMS = 'GET_ITEMS';

/actions/item.js

import * as ACTION_TYPES from '../action-types';
import * as API from '../../API';

const getItems = async count => {
  const getItemsResponse = await API.getItems();

  return {
    type: ACTION_TYPES.GET_ITEMS,
    payload: {
      items: getItemsResponse.data,
      count
    }
  };
};

export default getItems;

/reducers/item.js

import * as ACTION_TYPES from '../action-types';

const initialState = {
  items: [
    {
      id:1,
      name:'Item A',
      description: 'This is a pre-populated item for testing purposes.'
    }
  ]
}

const itemsReducer = (state, action) => {
  switch (action.type) {
    case ACTION_TYPES.GET_ITEMS:
      const { items } = action.payload;
      return { ...state, items }
      break;
    default:
      return state;
  }
}

最后,您可以将connect中的react-redux包裹在ItemComponent.js周围。以下代码应添加到文件中已存在的代码中 ItemComponent.js

const mapDispatchToPtops = {
    getItems
}

const mapStateToProp = state =>({
   items: state.itemsReducer.items
})

export default connect(mapStateToProp, mapDispatchToPtops)(ItemComponent)