杭州电子商务研究院

Redux 策略与异步数据和交互

2020-08-27 08:00飞浪

介绍

如今,React Redux 应用因其多功能性、可扩展性和无数功能而在网络上非常常见。使用操作和Reducer可以补充您的应用架构,并允许您在实现复杂功能的同时保持代码整洁。但是,当您需要使用异步操作(例如在收到服务器响应后调度操作)时,仅使用操作和Reducer是不够的。本指南演示了如何使用名为 redux-thunk 的 Redux 库与 React Redux 应用中的异步数据进行交互。

设置应用程序

在此示例中,您将开发一个简单的应用程序,该应用程序会从给定数组异步返回一个随机用户名作为字符串。为了实现这一点,您将使用一个名为thunk 的中间件,它允许您在操作到达Reducer之前对其进行拦截。

通过运行创建一个空白的 React 项目

      npx create-react-app react-thunk-app
    

安装 Redux 和 react-redux,这是在 React 应用中设置 Redux 的核心包

      npm i --save redux react-redux
    

安装 redux-thunk 以使用thunk

      npm i --save redux-thunk
    

创建商店

导入createStore为您的组件创建全局状态,并导入applyMiddleware以在您的商店中使用中间件。接下来从 redux-thunk导入thunk 。创建一个减速器rootReducer,它接受状态和操作并返回更新的状态。将rootReducer和applyMiddleware函数作为参数传递给createStore 。最后,使用thunk并将其作为参数传递给applyMiddleware。store.js中的大多数代码都是不言自明的,您可以看到它是多么容易,因此在您的 Redux 商店中使用thunk 。

      import {createStore,applyMiddleware} from 'redux';
import thunk from 'redux-thunk';

const initState={
    user:{}
}

const rootReducer=(state=initState,action)=>{
    switch(action.type){
        case "ADD_USER": 
            return{
            ...state,
            user: action.payload
        }
        default:
            return state;

    }   
}

export default createStore(rootReducer,applyMiddleware(thunk))
    

在index.js中从 Redux导入Provider ,并将您的store作为props传递给此提供程序组件。您还需要将整个应用程序包装在此提供程序组件中。

      import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
import {Provider} from 'react-redux';
import store from './store';

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

创建动作

在动作创建器中执行动作调度是一种很好的做法。考虑以下在actions.js文件中的代码,它接受dispatch和getState作为参数并调度类型为ADD_USER的动作。它在payload属性中返回newUser ,并从名为getRandomUse()的服务中获取此newUser。

      import {getRandomUser} from './service';

const ADD_USER="ADD_USER";

export const getRandomUserAction=()=>async(dispatch,getState)=>{
    const newUser= await getRandomUser()
    dispatch({
        type:ADD_USER,
        payload:newUser
    })
}
    

创建服务

您可以将getRandomUser()想象为从后端服务返回随机用户的函数。为简洁起见,以下代码模拟后端服务,并在三秒后从用户列表中返回一个随机用户的承诺。故意添加延迟以复制 API 响应的异步特性。在实际情况下,您将在此文件中对您的服务器进行 API 调用以获取一些数据。

      const users=['James','Michael','Harry','Sam','Dubby']

export const getRandomUser=()=>{
    return new Promise(resolve=>setTimeout(()=>{
        resolve(users[Math.floor(Math.random()*10)%users.length])
    },3000))
}
    

消费状态

在主App.js中,从 react-redux导入connect并从你的action.js导入 getRandomUser。创建一个函数mapStateToProps ,它从你的 store 中提取所需的状态,以便可以将其作为props传递给你的组件。创建一个对象mapDispatchToProps,将你的调度映射到一个可以作为props传递给你的组件的简单函数。调用connect()函数并传递mapStateToProps和mapDispatchToProps作为参数。最后,将你的应用组件包装在connect()函数中。现在你的 store 和操作已准备好供你的组件使用。

为了看到其实际效果,请创建一个简单的 UI 按钮,该按钮可触发getUser()函数并从状态中打印随机用户。

      import React,{useEffect} from 'react';
import {connect} from 'react-redux';
import {getRandomUserAction} from './actions';

import './App.css';

function App({getUser,user}) {
  useEffect(()=>{
    console.log(user)
  },[user])
  return (
    <div className="App">
      <button onClick={getUser}>Get a random user</button>
      {
        Object.values(user).length>0 ? user : <>No random user!</>
      }
    </div>
  );
}

const mapStateToProps=(state)=>({user:state.user})

const mapDispatchToProps={
  getUser:getRandomUserAction
}

export default connect(mapStateToProps,mapDispatchToProps)(App);
    

结论

使用thunk,您可以在操作到达 Reducer 之前与操作进行通信。thunk有许多围绕实际 Web 应用程序构建的用例,这些应用程序需要根据服务器的响应分派不同的操作。本指南中使用的示例可用作 React Redux 应用程序的样板,您需要在修改状态之前等待服务器的某些响应。

曝光26874浏览1439