此功能组件应在更改存储中的值的每个项上显示带有复选框的排序列表。
由于某些原因,当商店被更改时,它不会重新呈现。没有重新渲染器,它(和整个应用程序)的工作非常不正常和半途而废。我怀疑这是因为存储对象保持不变,尽管有新的内容。但我不知道怎么解决它。我甚至在复选框处理程序中插入了一个强制更新,但由于某种原因,它也不起作用。
构成部分:
import React, { useState, useReducer } from 'react';
import { ReactSortable } from 'react-sortablejs';
import ListItem from '@mui/material/ListItem';
import Checkbox from '@mui/material/Checkbox';
import { connect } from 'react-redux';
import { setGameVisible, setGameInvisible } from '../store/actions/games';
interface IGamesListProps {
games: [];
setGameVisible: (id: string) => void;
setGameInvisible: (id: string) => void;
}
interface ItemType {
id: string;
name: string;
isVisible: boolean;
}
const GamesList: React.FunctionComponent<IGamesListProps> = ({games, setGameVisible, setGameInvisible}) => {
const [state, setState] = useState<ItemType[]>(games);
// eslint-disable-next-line
const [ignored, forceUpdate] = useReducer(x => x + 1, 0); // this way of force updating is taken from the official React documentation (but even it doesn't work!)
const onCheckboxChangeHandle = (id: string, isVisible: boolean) => {
isVisible ? setGameInvisible(id) : setGameVisible(id);
forceUpdate(); // doesn't work :(((
}
return (
<ReactSortable list={state} setList={setState} tag='ul'>
{state.map((item) => (
<ListItem
sx={{ maxWidth: '300px' }}
key={item.id}
secondaryAction={
<Checkbox
edge="end"
onChange={() => onCheckboxChangeHandle(item.id, item.isVisible)}
checked={item.isVisible}
/>
}
>
{item.name}
</ListItem>
))}
</ReactSortable>
);
};
export default connect(null, { setGameVisible, setGameInvisible })(GamesList);减速机:
import { SET_GAMES, SET_GAME_VISIBLE, SET_GAME_INVISIBLE } from '../actions/games';
export const initialState = {
games: [],
};
export default function games(state = initialState, action) {
switch(action.type) {
case SET_GAMES: {
for(let obj of action.payload.games) {
obj.isVisible = true;
}
return {
...state,
games: action.payload.games,
};
}
case SET_GAME_VISIBLE: {
for(let obj of state.games) {
if (obj.id === action.payload.id) {
obj.isVisible = true;
};
}
return {
...state,
};
}
case SET_GAME_INVISIBLE: {
for(let obj of state.games) {
if (obj.id === action.payload.id) {
obj.isVisible = false;
};
}
return {
...state,
};
}
default:
return state;
}
}谢谢你的帮助!
发布于 2021-11-03 10:04:26
注意:根据你给我的信息,我是带着这个问题的想法来的,但我在这里发了帖子,因为它将是解释性的,而且很长。
mapStateToProps将新游戏传递到组件中,即使是这样,useState也不会使用新的游戏道具值进行非优先渲染。您必须使用useEffect并触发游戏更改,并将状态设置为本地.此时,
必须发现内部状态是多余的,您可以删除它并完全依赖于redux状态。
const mapStateToProp = (state) => ({
games: state.games // you may need to change the path
})
connect(mapStateToProp, { setGameVisible, setGameInvisible })(GamesList);state === state完成的。这可能不会引起问题,因为外部状态会发生变化,但我认为值得一提的是。for(let obj of action.payload.games) {
obj.isVisible = true; // mutating actions.payload.games[<item>]
}
return {
...state,
games: [...action.payload.games], // add immutability for re-redenr
};
// or use map
return {
...state,
games: action.payload.games.map(obj => ({...obj, isVisible:true})),
};forceUpdate确实会导致组件重新呈现,您可以通过添加console.log来测试它,但是如果组件的道具不改变,则不会重新绘制组件的整个子树,包括内部子树,这是因为性能问题。尽可能有效地做出反应。此外,如果项目和id的顺序不更改key ,则可以防止更改的优化层。
https://stackoverflow.com/questions/69821988
复制相似问题