My Little World

redux的基本使用

Redux 的三个基本概念

Redux 引入的概念其实并不多,主要就是三个:State、Action 和 Reducer。

其中 State 即 Store,一般就是一个纯 JavaScript Object。
Action 也是一个 Object,用于描述发生的动作。
而 Reducer 则是一个函数,接收 Action 和 State 并作为参数,通过计算得到新的 Store。

如何在 React 中使用 Redux

如何建立 Redux 和 React 的联系

主要是两点:

  1. React 组件能够在依赖的 Store 的数据发生变化时,重新 Render;
  2. 在 React 组件中,能够在某些时机去 dispatch 一个 action,从而触发 Store 的更新

答案:
借助react-redux 这样一个工具库,工具库的作用就是建立一个桥梁,让 React 和 Redux 实现互通。

在 react-redux 的实现中,为了确保需要绑定的组件能够访问到全局唯一的 Redux Store,
利用了 React 的 Context 机制去存放 Store 的信息。
通常我们会将这个 Context 作为整个 React 应用程序的根节点。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import React from 'react'
import ReactDOM from 'react-dom'

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

import App from './App'

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

Hooks 的本质就是提供了让 React 组件能够绑定到某个可变的数据源的能力。
在这里,当 Hooks 用到 Redux 时可变的对象就是 Store,而 useSelector 则让一个组件能够在 Store 的某些数据发生变化时重新 render.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25


import React from 'react'
import { useSelector, useDispatch } from 'react-redux'

export function Counter() {
// 从 state 中获取当前的计数值
const count = useSelector(state => state.value)

// 获得当前 store 的 dispatch 方法
const dispatch = useDispatch()

// 在按钮的 click 时间中去分发 action 来修改 store
return (
<div>
<button
onClick={() => dispatch({ type: 'counter/incremented' })}
>+</button>
<span>{count}</span>
<button
onClick={() => dispatch({ type: 'counter/decremented' })}
>-</button>
</div>
)
}

使用 Redux 处理异步逻辑

借助中间件机制

middleware 可以让你提供一个拦截器在 reducer 处理 action 之前被调用。
在这个拦截器中,你可以自由处理获得的 action。
无论是把这个 action 直接传递到 reducer,或者构建新的 action 发送到 reducer,都是可以的

Middleware 正是在 Action 真正到达 Reducer 之前提供的一个额外处理 Action 的机会

Redux 提供了 redux-thunk 这样一个中间件,它如果发现接受到的 action 是一个函数,那么就不会传递给 Reducer,
而是执行这个函数,并把 dispatch 作为参数传给这个函数,从而在这个函数中你可以自由决定何时,如何发送 Action。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// 在创建 Redux Store 时指定了 redux-thunk 这个中间件
import { createStore, applyMiddleware } from 'redux'
import thunkMiddleware from 'redux-thunk'
import rootReducer from './reducer'

const composedEnhancer = applyMiddleware(thunkMiddleware)
const store = createStore(rootReducer, composedEnhancer)

//dispatch action 时就可以 dispatch 一个函数用于来发送请求

function fetchData() {
return dispatch => {
dispatch({ type: 'FETCH_DATA_BEGIN' });
fetch('/some-url').then(res => {
dispatch({ type: 'FETCH_DATA_SUCCESS', data: res });
}).catch(err => {
dispatch({ type: 'FETCH_DATA_FAILURE', error: err });
})
}
}

// dispatch action 时就可以 dispatch 一个函数用于来发送请求
import fetchData from './fetchData';

function DataList() {
const dispatch = useDispatch();
// dispatch 了一个函数由 redux-thunk 中间件去执行
dispatch(fetchData());
}

通过这种方式,我们就实现了异步请求逻辑的重用。那么这一套结合 redux-thunk 中间件的机制,我们就称之为异步 Action.

dispatch时可以传入其他参数

1
2
3
4
5
6
7
8
9
10
11
12

function counterReducer(state = initialState, action) {
switch (action.type) {
case 'counter/incremented': return {value: state.value + action.payload}
case 'counter/decremented': return {value: state.value - action.payload}
default: return state
}
}
const incrementAction = { type: 'counter/incremented', payload: 10 };
store.dispatch(incrementAction); // 计数器加 10
const decrementAction = { type: 'counter/decremented', payload: 10 };
store.dispatch(decrementAction); // 计数器减 10