我创建了三个useSelector挂钩,对于第一个,我通过使用OnClick函数调度动作来更改值。当我这样做时,即使引用没有更改,我的其他useSelects也会重新呈现。有人知道为什么会这样吗?我相信这是因为我将console.logs放在useSelectors中,并且每次单击按钮时它们都会被触发。单击按钮时,minedDiamond 应该 是唯一要更改的值。
Minecraft.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;
答案 0 :(得分:2)
您的问题与console.log的使用无关。 您能否为动作创建者和还原者添加代码?
假设state.diamond.mincraftdata是一个数组,一行
return data.map((i) => i.name);
每次运行选择器时,都会创建一个新数组。按照react-redux docs:
当一个动作被分派给Redux的商店,useSelector()只迫使如果选择结果似乎比最后的结果不同重新绘制。从v7.1.0-alpha.5开始,默认比较是严格的===参考比较。