我想,redux的名声在前端领域里应该是非常响亮的。而对应的,它的社区也是非常活跃,因此,当我们希望在一个React项目中引入redux进行状态管理的话,我们只需要引入react-redux
下边的例子中,会引入redux-thunk让store支持异步更新
实际上,在react-redux中我们只需要了解这三个概念即可使用redux,而实际上这些也不难理解。我们只要掌握一些关键的api,尤其是hook,就可以很轻松地在我们的项目中加入redux
store的概念是什么?我们完全可以将store当成一个state总仓库,当成一个超大的state
正常来讲 组件与组件之间传值的关系是这样的
我们可以看到,当我们试图把father组件的state值传到child-2-1这个三级组件,并且保证每次更新state可以使得child-2-1接收到,在没有hook之前我们不得不一层层把state下传,这无疑让组件的可维护性大大降低,增加了很多繁杂的代码。
引入redux 而在我们引入redux后,结构关系就变成了这样
我们的放在store中的state不必再依赖于层层传递,当store中我们希望获得的state更新的时候,会触发通知到订阅了该state的组件,从而完成视图更新
然众所周知万事开头难,我们把store.js的文件代码直接放上,这里可以直接抄
import { createStore, applyMiddleware, compose } from "redux";
import thunk from "redux-thunk";
import rootReducer from "../reducers";
// 添加支持浏览器redux插件
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(
rootReducer,
composeEnhancers(applyMiddleware(thunk))
);
export default store;
action是触发store中state更新的行为
其实也非常好理解,我们还是先看看原本的state更新。可以看到,直接修改组件的state是无法触发视图层更新的。在store中,类似的,store中的state是只读的,我们想要更新store中的state,只能通过预先制定好的action触发更新。
// class组件
this.setState({
state0:1
})
// function组件
function Component(){
const [state0,setState0]=useState(0);
setState0(1);
}
//错误做法
this.state0=1
而使用redux的话,通常我们用这种形式更新
dispatch({
type:"setState0",
payload:1
})
注意这里的dispatch和上方的setState作用上是类似的,而action是它发出去的内容
const controlNav = () => dispatch => {
dispatch({
type: "controlNav"
})
};
export {controlNav}
我们上边讲到了action,但action发出后当然不是直接更新state,实际上,store收到action后,要先经过reducer处理,才可以更新相关的state
const initialState={
state0:0
}
const navReducer = (state = initialState, action) => {
switch (action.type) {
case "setState0":
state.state0=action.payload
return {...state}
case "clearState0":
state.state0=0
return {...state}
default:
return state;
}
}
这里值得注意的是,更新是需要进行深拷贝的,并且reducer应该是纯函数
import {combineReducers} from "redux";
import linkReducer from "./linkReducer";
import navReducer from "./navReducer";
import workspaceReducer from "./workspaceReducer";
import orderReducer from "./orderReducer";
const rootReducer = combineReducers({
linkReducer,navReducer,workspaceReducer,orderReducer
});
export default rootReducer;
那么最好形成的目录结构如下:
function WorkSpace(){
const initData=useSelector(item=>item.workspaceReducer.initData)
}
当我们更新initData的时候,组件WorkSpace中的initData会收到更新并且重新渲染组件
我们可以通过dispatch在组件中更新store中的state
import { handleWorkSpaceShow } from "../../../actions/workspace";
function Workspace() {
const dispatch = useDispatch();
dispatch(handleWorkSpaceShow());
}
这其中的handleWorkSpaceShow是一个action,具体如下:
const handleWorkSpaceShow = (val) => (dispatch) => {
dispatch({
type: "handleWorkSpaceShow",
payload:{
data:val
}
})
};
然后对应"handleWorkSpaceShow"
这个type,reducer是这样工作的
const workspaceReducer = (state = initialState, action) => {
switch (action.type) {
case "handleWorkSpaceShow":
state.running = action.payload.data;
state.startTimeStamp = new Date().getTime();
return { ...state };
default:
return { ...state };
}
};
通过上述步骤,其实我们就已经可以对store进行维护
当然别忘了,事先要在最外层加一层Provider:
ReactDOM.render(
<React.StrictMode>
<Provider store={store}>
<Router>
<Suspense fallback={<div>Loading...</div>}>
<Route path="/net" component={Nav} />
<Route path="/net" component={NetIndex} />
<Route path="/login" component={Login} />
</Suspense>
</Router>
</Provider>
</React.StrictMode>,
document.getElementById("root")
);