hook+react-redux让redux使用更简单

2022-08-12 11:30:16 浏览数 (1)

我想,redux的名声在前端领域里应该是非常响亮的。而对应的,它的社区也是非常活跃,因此,当我们希望在一个React项目中引入redux进行状态管理的话,我们只需要引入react-redux

下边的例子中,会引入redux-thunk让store支持异步更新

redux核心概念

  • store
  • action
  • reducer

实际上,在react-redux中我们只需要了解这三个概念即可使用redux,而实际上这些也不难理解。我们只要掌握一些关键的api,尤其是hook,就可以很轻松地在我们的项目中加入redux

store

store的概念是什么?我们完全可以将store当成一个state总仓库,当成一个超大的state

正常来讲 组件与组件之间传值的关系是这样的

我们可以看到,当我们试图把father组件的state值传到child-2-1这个三级组件,并且保证每次更新state可以使得child-2-1接收到,在没有hook之前我们不得不一层层把state下传,这无疑让组件的可维护性大大降低,增加了很多繁杂的代码。

引入redux 而在我们引入redux后,结构关系就变成了这样

我们的放在store中的state不必再依赖于层层传递,当store中我们希望获得的state更新的时候,会触发通知到订阅了该state的组件,从而完成视图更新

然众所周知万事开头难,我们把store.js的文件代码直接放上,这里可以直接抄

  • store.js
代码语言:javascript复制
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

action是触发store中state更新的行为

其实也非常好理解,我们还是先看看原本的state更新。可以看到,直接修改组件的state是无法触发视图层更新的。在store中,类似的,store中的state是只读的,我们想要更新store中的state,只能通过预先制定好的action触发更新。

代码语言:javascript复制
// class组件
this.setState({
    state0:1
})
// function组件
function Component(){
    const [state0,setState0]=useState(0);
    setState0(1);
}
//错误做法
this.state0=1

而使用redux的话,通常我们用这种形式更新

代码语言:javascript复制
dispatch({
   type:"setState0",
   payload:1
})

注意这里的dispatch和上方的setState作用上是类似的,而action是它发出去的内容

  • action框架
代码语言:javascript复制
const controlNav = () => dispatch => {
    dispatch({
      type: "controlNav"
    })
  };
export {controlNav}

reducer

我们上边讲到了action,但action发出后当然不是直接更新state,实际上,store收到action后,要先经过reducer处理,才可以更新相关的state

代码语言:javascript复制
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应该是纯函数

  • reducers目录
代码语言:javascript复制
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;

那么最好形成的目录结构如下:

用hook简化操作

useSelector 接收state的更新

代码语言:javascript复制
function WorkSpace(){
    const initData=useSelector(item=>item.workspaceReducer.initData)
}

当我们更新initData的时候,组件WorkSpace中的initData会收到更新并且重新渲染组件

useDispatch 发出action从而更新state

我们可以通过dispatch在组件中更新store中的state

代码语言:javascript复制
import { handleWorkSpaceShow } from "../../../actions/workspace";
function Workspace() {
  const dispatch = useDispatch();
  dispatch(handleWorkSpaceShow());
}

对应的action

这其中的handleWorkSpaceShow是一个action,具体如下:

代码语言:javascript复制
const handleWorkSpaceShow = (val) => (dispatch) => {
  dispatch({
    type: "handleWorkSpaceShow",
    payload:{
      data:val
    }
  })
};

对应的reducer

然后对应"handleWorkSpaceShow"这个type,reducer是这样工作的

代码语言:javascript复制
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:

代码语言:javascript复制
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")
);

0 人点赞