reactjs - Redux UseSelect 钩子不断重新渲染
问题描述
我创建了三个 useSelector 挂钩,对于第一个挂钩,我通过使用 OnClick 函数调度操作来更改值。当我这样做时,即使引用没有改变,我的其他 useSelects 也会重新渲染。有谁知道为什么会这样?我相信这种情况正在发生,因为我将 console.logs 放在 useSelectors 中,并且每次单击按钮时都会看到它们被触发。当我单击按钮时, minedDiamond应该是唯一更改的值。
我的世界.js
import React, { useEffect, useCallback } from "react";
import { connect, useSelector, useDispatch, shallowEqual } from "react-redux";
import { mineDiamond, fetchMinecraftItems } from "../redux/diamonds/actions";
const Minecraft = () => {
const loading = useSelector((state) => {
console.log("loading output");
return state.diamond.loading;
});
let minedDiamond = useSelector((state) => {
console.log("diamond output");
return state.diamond.minedDiamond;
});
const names = useSelector((state) => {
console.log("name rendered");
let data = state.diamond.minecraftData;
return data.map((i) => i.name);
});
const dispatch = useDispatch();
const handleClick = () => dispatch(mineDiamond((minedDiamond += 1)));
useEffect(() => {
dispatch(fetchMinecraftItems());
}, []);
console.log({ loading });
return (
<div className="wrapper">
<div className="wrapper__item">
<img src="/image/pickaxe.png" alt="diamond" />
<button onClick={handleClick} type="button" className="wrapper__button">
Mine
<span role="img" aria-label="cart">
</span>
</button>
</div>
<div className="wrapper__item">
<img src="/image/diamond.png" alt="axe" />
<span className="num">{minedDiamond}</span>
</div>
<div className="num">
{loading ? (
<p>loading...</p>
) : (
<h1 className="num">{names}</h1>
)}
</div>
</div>
);
};
export default Minecraft;
动作创作者
import * as Actions from "./actionTypes";
import axios from "axios";
//action creator
export const mineDiamond = (addDiamond) => ({
type: Actions.MINE_DIAMOND,
payload: addDiamond,
});
export function fetchMinecraftItems() {
return function (dispatch) {
dispatch({ type: Actions.MINECRAFT_DATA_FETCH });
return fetch("https://jsonplaceholder.typicode.com/users")
.then((response) => response.json())
.then((json) => {
dispatch({ type: Actions.MINECRAFT_DATA_SUCCESS, payload: json });
})
.catch((err) =>
dispatch({ type: Actions.MINECRAFT_DATA_FAIL, payload: err })
);
};
}
减速器
import * as Actions from "./actionTypes";
//reducer holds initial state
const initialState = {
minedDiamond: 0,
minecraftData: [],
loading: false,
error: null,
};
//reducer
const diamondReducer = (state = initialState, action) => {
switch (action.type) {
case Actions.MINE_DIAMOND:
return {
...state,
minedDiamond: action.payload,
};
case Actions.MINECRAFT_DATA_FETCH:
return {
...state,
loading: true,
};
case Actions.MINECRAFT_DATA_SUCCESS:
return {
...state,
loading: false,
minecraftData: action.payload,
};
case Actions.MINECRAFT_DATA_FAIL:
return {
...state,
error: action.payload,
};
default:
return state;
}
};
export default diamondReducer;
解决方案
您的问题与 console.log 的使用无关。您能否为您的动作创建者和减速者提供代码?
假设 state.diamond.mincraftdata 是一个数组,这条线
return data.map((i) => i.name);
每次运行选择器时都会创建一个新数组。根据react-redux 文档:
当一个动作被分派到 Redux 存储时,useSelector() 仅在选择器结果看起来与上一个结果不同时才强制重新渲染。从 v7.1.0-alpha.5 开始,默认比较是严格的 === 参考比较。
推荐阅读
- function - Oauth token sharing for multiple Cloud Function instances
- ios - Cannot use Gifu Pod in my app "GIF doesn't appear"
- mysql - 在客户姓名旁边添加客户姓名
- mongodb - Will my MongoRestore operation crash my database?
- c++ - 如何安全地引用 std::vector 元素?
- node.js - Nextjs TypeError:没有'new'就不能调用类构造函数调用
- java - 后映射不起作用,给出 405 方法不允许错误
- image - 如何在 Rundeck 中调整徽标大小?
- javafx - 在 JavaFX 中构建场景后按钮不会改变颜色
- php - PHP - 按关键内容合并大型数组