redux-hook

作者: 未路过 | 来源:发表于2022-10-31 23:14 被阅读0次

1.用RTK和react-redux实现的count

import { configureStore } from "@reduxjs/toolkit";
import countReducer from "./modules/count";

const Store = configureStore({
  reducer: {
    count: countReducer,
  },
});

export default Store;
import { createSlice } from "@reduxjs/toolkit";

const counterSlice = createSlice({
  name: "count",
  initialState: {
    count: 0,
  },
  reducers: {
    addNumberAction(state, { payload }) {
      state.count = state.count + payload;
    },
    subNumberAction(state, { payload }) {
      state.count = state.count - payload;
    },
  },
});

export const { addNumberAction, subNumberAction } = counterSlice.actions;
export default counterSlice.reducer;

import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import store from "./store/store";
import { Provider } from "react-redux";
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 { addNumberAction, subNumberAction } from "./store/modules/count";
const App = memo((props) => {
  const { count, addNumber, subNumber } = props;
  const addNumberClick = () => {
    addNumber(1);
  };
  const subNumberClick = () => {
    subNumber(1);
  };
  return (
    <div>
      <h2>{count}</h2>
      <button onClick={addNumberClick}>加1</button>
      <button onClick={subNumberClick}>减1</button>
    </div>
  );
});
const mapStateToProps = (state) => {
  return {
    count: state.count.count,
  };
};
const mapDispatchToProps = (dispatch) => {
  return {
    addNumber(num) {
      dispatch(addNumberAction(num));
    },
    subNumber(num) {
      dispatch(subNumberAction(num));
    },
  };
};

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

RTK就是简单版的store
react-redux就是让组件不直接操作store这个对象,在外面通过connect函数封装了一层,产生了一个组件。

每个组件都要写这个

const mapStateToProps = (state) => {
  return {
    count: state.count.count,
  };
};
const mapDispatchToProps = (dispatch) => {
  return {
    addNumber(num) {
      dispatch(addNumberAction(num));
    },
    subNumber(num) {
      dispatch(subNumberAction(num));
    },
  };
};

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

很麻烦。

2.useSelector() useDispatch()

import React, { memo } from "react";
import { useSelector, useDispatch } from "react-redux";
import { addNumberAction, subNumberAction } from "./store/modules/count";
const App = memo(() => {
  /* 1.使用useSelector将redux中store的数据映射到组件中 , 和mapStateToProps很相似*/
  const { count } = useSelector((state) => {
    return {
      count: state.count.count,
    };
  });

  /* 2.使用useDispatch,直接派发action */
  const dispatch = useDispatch();

  const addNumberClick = () => {
    dispatch(addNumberAction(1));
  };
  const subNumberClick = () => {
    dispatch(subNumberAction(1));
  };
  return (
    <div>
      <h2>{count}</h2>
      <button onClick={addNumberClick}>加1</button>
      <button onClick={subNumberClick}>减1</button>
    </div>
  );
});

export default App;

image.png

3.useSelector的浅层比较性

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

const Home = memo(() => {
  const { message } = useSelector((state) => {
    return {
      message: state.count.message,
    };
  });

  console.log("Home render");

  return <h2>Home:{message}</h2>;
});

const App = memo(() => {
  /* 1.使用useSelector将redux中store的数据映射到组件中 , 和mapStateToProps很相似*/
  const { count } = useSelector((state) => {
    return {
      count: state.count.count,
    };
  });

  /* 2.使用useDispatch,直接派发action */
  const dispatch = useDispatch();

  console.log("App render");
  const addNumberClick = () => {
    dispatch(addNumberAction(1));
  };
  const subNumberClick = () => {
    dispatch(subNumberAction(1));
  };
  return (
    <div>
      <h2>{count}</h2>
      <button onClick={addNumberClick}>加1</button>
      <button onClick={subNumberClick}>减1</button>
      <hr></hr>
      <Home></Home>
    </div>
  );
});

export default App;

在app里面点击按钮,app和home都会render。app里面使用的count改变了,渲染是正常的,但是home依赖的message没有改变。
按道理,如果home没有包裹memo,那么app重新渲染,home肯定也会重新渲染。

memo高阶组件包裹起来的组件有相应的特点:
只有props发送该百年的时候,才会重新渲染。
如果home里面没有使用任何state里面的数据,那么点击app的按钮,只有app render。

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

const Home = memo(() => {
  console.log("Home render");

  return <h2>Home</h2>;
});

const App = memo(() => {
  /* 1.使用useSelector将redux中store的数据映射到组件中 , 和mapStateToProps很相似*/
  const { count } = useSelector((state) => {
    return {
      count: state.count.count,
    };
  });

  /* 2.使用useDispatch,直接派发action */
  const dispatch = useDispatch();

  console.log("App render");
  const addNumberClick = () => {
    dispatch(addNumberAction(1));
  };
  const subNumberClick = () => {
    dispatch(subNumberAction(1));
  };
  return (
    <div>
      <h2>{count}</h2>
      <button onClick={addNumberClick}>加1</button>
      <button onClick={subNumberClick}>减1</button>
      <hr></hr>
      <Home></Home>
    </div>
  );
});

export default App;

memo 去掉就会home也会渲染。
home里面有useSeletcor,别的组件改变state,它也会重新渲染。
原因:因为默认情况下,useSeletcor监听的是整个state,
只要state发生改变了,组件就会重新渲染。
state:{count:0, message:"hello world"}
app改变了count,home使用的是message,message没有改变
性能不高。
在home修改message,app也会重新渲染。

这个时候,
useSelector的作用是将state映射到组件中:
 参数一:将state映射到需要的数据中;
 参数二:可以进行比较来决定是否组件重新渲染;(后续讲解)

import React, { memo } from "react";
import { useSelector, useDispatch, shallowEqual } from "react-redux";
import {
  addNumberAction,
  changeMessageAction,
  subNumberAction,
} from "./store/modules/count";

const Home = memo(() => {
  /* 本次映射出来的数据和上次映射出来的数据进行比较,看看message有没有改变,只有改变,才让当前组件渲染 */
  const { message } = useSelector((state) => {
    return {
      message: state.count.message,
    };
  }, shallowEqual);
  const dispatch = useDispatch();
  console.log("Home render");
  const changemessage = () => {
    dispatch(changeMessageAction("changed message"));
  };

  return (
    <div>
      <h2>Home:{message}</h2>
      <button onClick={(e) => changemessage()}>改变message</button>
    </div>
  );
});

const App = memo(() => {
  /* 1.使用useSelector将redux中store的数据映射到组件中 , 和mapStateToProps很相似*/
  const { count } = useSelector((state) => {
    return {
      count: state.count.count,
    };
  });

  /* 2.使用useDispatch,直接派发action */
  const dispatch = useDispatch();

  console.log("App render");
  const addNumberClick = () => {
    dispatch(addNumberAction(1));
  };
  const subNumberClick = () => {
    dispatch(subNumberAction(1));
  };
  return (
    <div>
      <h2>{count}</h2>
      <button onClick={addNumberClick}>加1</button>
      <button onClick={subNumberClick}>减1</button>
      <hr></hr>
      <Home></Home>
    </div>
  );
});

export default App;

给home的useSelector添加第二个参数shallowEqual,
那么只有返回的这个状态和上次返回的这个状态不同的时候,才会更新组件。
这次,点击app的按钮,也只有app才会渲染。
改变message,也只有home才会渲染。

相关文章

  • redux-hook

    1.用RTK和react-redux实现的count RTK就是简单版的storereact-redux就是让组件...

网友评论

    本文标题:redux-hook

    本文链接:https://www.haomeiwen.com/subject/ghnltdtx.html