我在 React 18 应用程序中使用 Redux 5。当使用
useSelector()
包中的 react-redux
方法时,我在浏览器控制台中收到以下警告:
Selector unknown returned the root state when called. This can lead to unnecessary rerenders.
Selectors that return the entire state are almost certainly a mistake, as they will cause a rerender whenever *anything* in state changes.
我还在https://react-redux.js.org/api/hooks#identity-function-state--state-check看到了此警告的redux文档,但是,我面临的问题是我的代码中的“状态是一个数组”。请参阅下面我的文件:
Notes.jsx
import { useDispatch, useSelector } from 'react-redux';
import { toggleImportanceOf } from '../reducers/noteReducer';
const Note = ({ note, handleClick }) => {
return (
<li onClick={handleClick}>
{note.content}
<strong> {note.important ? 'important' : ''}</strong>
</li>
);
};
const Notes = () => {
const dispatch = useDispatch();
const notes = useSelector((state) => {
console.log(state); // THIS IS AN ARRAY
return state;
});
return (
<ul>
{notes.map((note) => (
<Note
key={note.id}
note={note}
handleClick={() => dispatch(toggleImportanceOf(note.id))}
/>
))}
</ul>
);
};
export default Notes;
noteReducer.js
是我的减速机
const noteReducer = (state = [], action) => {
switch (action.type) {
case 'NEW_NOTE':
return [...state, action.payload];
case 'TOGGLE_IMPORTANCE': {
const id = action.payload.id;
const noteToChange = state.find((n) => n.id === id);
const changedNote = {
...noteToChange,
important: !noteToChange.important,
};
return state.map((note) => (note.id !== id ? note : changedNote));
}
default:
return state;
}
};
const generateId = () => Number((Math.random() * 1000000).toFixed(0));
export const createNote = (content) => {
return {
type: 'NEW_NOTE',
payload: {
content,
important: false,
id: generateId(),
},
};
};
export const toggleImportanceOf = (id) => {
return {
type: 'TOGGLE_IMPORTANCE',
payload: { id },
};
};
export default noteReducer;
main.jsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import App from './App';
import noteReducer from './reducers/noteReducer';
const store = createStore(noteReducer);
ReactDOM.createRoot(document.getElementById('root')).render(
<Provider store={store}>
<App />
</Provider>
);
请注意,我知道
createStore
已被弃用。这只是入门课程,我们将学习取代 createStore
方法的新方法。
状态数组如下:
数组内容填充到表单中,然后列表呈现在 UI 上。请看下图:
问题:如何在浏览器控制台中针对数组“状态”修复此警告?
基本上你不应该有一个返回整个状态对象的选择器函数。
将
notes
状态嵌套在状态中的 notes
属性下并选择该属性。
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import { Provider } from "react-redux";
import { createStore, combineReducers } from "redux";
import App from "./App";
import noteReducer from "./reducers/noteReducer";
// Create a root reducer function
const rootReducer = combineReducers({
notes: noteReducer // <-- note reducer forms state.notes
});
const store = createStore(rootReducer);
const rootElement = document.getElementById("root");
const root = createRoot(rootElement);
root.render(
<StrictMode>
<Provider store={store}>
<App />
</Provider>
</StrictMode>
);
import { useDispatch, useSelector } from "react-redux";
import { toggleImportanceOf } from "./reducers/noteReducer";
import { useEffect } from "react";
const Note = ({ note, handleClick }) => {
return (
<li onClick={handleClick}>
{note.content}
<strong> {note.important ? "important" : ""}</strong>
</li>
);
};
const Notes = () => {
const dispatch = useDispatch();
const notes = useSelector((state) => state.notes); // <-- select state.notes array
useEffect(() => {
console.log(notes);
}, [notes]);
return (
<ul>
{notes.map((note) => (
<Note
key={note.id}
note={note}
handleClick={() => dispatch(toggleImportanceOf(note.id))}
/>
))}
</ul>
);
};
export default Notes;
另请注意,您还将了解什么是实际上“已弃用”的 Redux。现代 Redux 是使用 Redux-Toolkit 库编写的,该库更加精简且样板代码更少。