React18,RTK对比,redux-hooks;shallowEqual, useDispatch, useSelector

240 阅读2分钟

redux-hooks

image.png

  • npm i @reduxjs/toolkit react-redux

组件 <-> store 怎么联系起来

connect用法

import { configureStore } from "@reduxjs/toolkit";
import countReducer from "./modules/count";
const store = configureStore({
  reducer: {
    counter: countReducer,
  },
});
export default store;
import { createSlice } from "@reduxjs/toolkit";
const countSlice = createSlice({
  name: "count",
  initialState: {
    count: 100,
  },
  reducers: {
    addAction(state, { payload }) {
      state.count = state.count + payload;
    },
    subAction(state, { payload }) {
      state.count = state.count - payload;
    },
  },
});
export const { addAction, subAction } = countSlice.actions;
export default countSlice.reducer;
import App from "./pages-learn-hooks/redux-hooks使用/App";
import { Provider } from "react-redux";
import store from "./pages-learn-hooks/redux-hooks使用/store";

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
      <Provider store={store}>
        <App />
      </Provider>
);
import React, { memo } from "react";
import { connect } from "react-redux";
import { addAction, subAction } from "./store/modules/count";
const App = memo((props) => {
  const { count, add, sub } = props;
  function addNumHandle(num, isAdd = true) {
    if (isAdd) {
      add(num);
    } else {
      sub(num);
    }
  }
  return (
    <div>
      <h2>Redux-Hooks App Page</h2>
      <div>
        <h2>当前计数:{count}</h2>
        <button onClick={(e) => addNumHandle(1)}>+1</button>
        <button onClick={(e) => addNumHandle(6)}>+6</button>
        <button onClick={(e) => addNumHandle(6, false)}>-6</button>
      </div>
    </div>
  );
});

const mapStateToProps = (state) => ({
  count: state.counter.count,
});

const mapDispatchToProps = (dispatch) => ({
  add(num) {
    dispatch(addAction(num));
  },
  sub(num) {
    dispatch(subAction(num));
  },
});
export default connect(mapStateToProps, mapDispatchToProps)(App);

image.png

hooks用法

import React, { memo } from "react";
import { addAction, subAction } from "./store/modules/count";
import { useDispatch, useSelector } from "react-redux";

const App = memo((props) => {
  // 1.使用useSelector将redux中store的数据映射到组件内
  const { count } = useSelector((state) => ({
    count: state.counter.count,
  }));

  // 2.使用dispatch直接派发action
  const dispatch = useDispatch();
  function addNumHandle(num, isAdd = true) {
    if (isAdd) {
      dispatch(addAction(num));
    } else {
      dispatch(subAction(num));
    }
  }
  return (
    <div>
      <h2>Redux-Hooks App Page</h2>
      <div>
        <h2>当前计数:{count}</h2>
        <button onClick={(e) => addNumHandle(1)}>+1</button>
        <button onClick={(e) => addNumHandle(6)}>+6</button>
        <button onClick={(e) => addNumHandle(6, false)}>-6</button>
      </div>
    </div>
  );
});
export default App;

useSelector的使用下面的代码有问题:

import React, { memo } from "react";
import { addAction, changeMsgAction, subAction } from "./store/modules/count";
import { useDispatch, useSelector } from "react-redux";

const Home = memo((props) => {
  const { msg } = useSelector((state) => ({
    msg: state.counter.msg,
  }));
  const dispatch = useDispatch();
  function changeMsgHandle() {
    dispatch(changeMsgAction("hello,ww999"));
  }
  console.log("Home render");
  return (
    <div>
      <h2>msg:{msg}</h2>
      <button onClick={(e) => changeMsgHandle()}>changeMsg</button>
    </div>
  );
});

const App = memo((props) => {
  // 1.使用useSelector将redux中store的数据映射到组件内
  const { count } = useSelector((state) => ({
    count: state.counter.count,
  }));

  // 2.使用dispatch直接派发action
  const dispatch = useDispatch();
  function addNumHandle(num, isAdd = true) {
    if (isAdd) {
      dispatch(addAction(num));
    } else {
      dispatch(subAction(num));
    }
  }
  console.log("App render");
  return (
    <div>
      <h2>Redux-Hooks App Page</h2>
      <div>
        <h2>当前计数:{count}</h2>
        <button onClick={(e) => addNumHandle(1)}>+1</button>
        <button onClick={(e) => addNumHandle(6)}>+6</button>
        <button onClick={(e) => addNumHandle(6, false)}>-6</button>
      </div>
      <Home />
    </div>
  );
});
export default App;

useSelector()-----msg或者count修改了,都会引起App和Home组件重新渲染

优化: shallowEqual

import React, { memo } from "react";
import { addAction, changeMsgAction, subAction } from "./store/modules/count";
import { shallowEqual, useDispatch, useSelector } from "react-redux";

const Home = memo((props) => {
  const { msg } = useSelector(
    (state) => ({
      msg: state.counter.msg,
    }),
    shallowEqual
  );
  const dispatch = useDispatch();
  function changeMsgHandle() {
    dispatch(changeMsgAction("hello,ww999"));
  }
  console.log("Home render");
  return (
    <div>
      <h2>msg:{msg}</h2>
      <button onClick={(e) => changeMsgHandle()}>changeMsg</button>
    </div>
  );
});

const App = memo((props) => {
  // 1.使用useSelector将redux中store的数据映射到组件内
  const { count } = useSelector(
    (state) => ({
      count: state.counter.count,
    }),
    shallowEqual
  );

  // 2.使用dispatch直接派发action
  const dispatch = useDispatch();
  function addNumHandle(num, isAdd = true) {
    if (isAdd) {
      dispatch(addAction(num));
    } else {
      dispatch(subAction(num));
    }
  }
  console.log("App render");
  return (
    <div>
      <h2>Redux-Hooks App Page</h2>
      <div>
        <h2>当前计数:{count}</h2>
        <button onClick={(e) => addNumHandle(1)}>+1</button>
        <button onClick={(e) => addNumHandle(6)}>+6</button>
        <button onClick={(e) => addNumHandle(6, false)}>-6</button>
      </div>
      <Home />
    </div>
  );
});
export default App;