因此,我正在使用React Context API来管理我的应用程序的某些全局状态
const blueprintList = [
{
id: new Date().toISOString(),
name: 'Getting started',
color: '#c04af6',
code: '<h1>Hello World!</h1>,
},
];
export const BlueprintsContext = createContext();
export const BlueprintsProvider = ({ children }) => {
const [blueprints, setBlueprints] = useState(blueprintList);
let [selected, setSelected] = useState(0);
const [count, setCount] = useState(blueprints.length);
useEffect(() => {
setCount(blueprints.length);
}, [blueprints]);
// just for debugging
useEffect(() => {
console.log(`DEBUG ==> ${selected}`);
}, [selected]);
const create = blueprint => {
blueprint.id = new Date().toISOString();
setBlueprints(blueprints => [...blueprints, blueprint]);
setSelected(count);
};
const remove = blueprint => {
if (count === 1) return;
setBlueprints(blueprints => blueprints.filter(b => b.id !== blueprint.id));
setSelected(-1);
};
const select = blueprint => {
const index = blueprints.indexOf(blueprint);
if (index !== -1) {
setSelected(index);
}
};
const value = {
blueprints,
count,
selected,
select,
create,
remove,
};
return (
<BlueprintsContext.Provider value={value}>
{children}
</BlueprintsContext.Provider>
);
};
然后,我在这样的组件内部使用删除功能。
const Blueprint = ({ blueprint, isSelected }) => {
const { select, remove } = useContext(BlueprintsContext);
return (
<div
className={classnames(`${CSS.blueprint}`, {
[`${CSS.blueprintActive}`]: isSelected,
})}
key={blueprint.id}
onClick={() => select(blueprint)}
>
<div
className={CSS.blueprintDot}
style={{ backgroundColor: blueprint.color }}
/>
<span
className={classnames(`${CSS.blueprintText}`, {
['text-gray-300']: isSelected,
['text-gray-600']: !isSelected,
})}
>
{blueprint.name}
</span>
{isSelected && (
<IoMdClose className={CSS.close} onClick={() => remove(blueprint)} />
)}
</div>
);
};
父组件会收到一个项目列表,并为每个项目呈现一个 Blueprint 组件。问题在于,当按下IoMdClose图标时,该项目将从列表中删除,但 selected 值不会更新为-1。 ?♂️
答案 0 :(得分:1)
Ciao,我发现了您的问题:在函数select
中,您已经设置了selected
:
const select = blueprint => {
const index = blueprints.indexOf(blueprint);
if (index !== -1) {
setSelected(index); // here you set selected
}
};
当您单击IoMdClose
图标时,也会触发select
。结果就是这个useEffect
:
useEffect(() => {
console.log(`DEBUG ==> ${selected}`);
}, [selected]);
不记录任何内容。
我尝试从setSelected(index);
函数中删除select
,当我单击IoMdClose
图标时,selected
将设置为-1,并使用效果日志DEBUG ==> -1
但是现在您遇到另一个问题:如果从setSelected(index);
中删除select
,并且尝试从左侧树视图中选择一个蓝图,则不会选择该蓝图。因此,我在setSelected(index);
函数中重新添加了select
。从setSelected(-1);
函数中删除了remove
,现在useEffect不会记录任何内容!
我认为发生这种情况是因为您试图将selected
设置为不存在的索引(因为在单击图标时删除了蓝图)。为了验证这一点,我将setSelected(index);
函数中的select
修改为setSelected(0);
并立即生效,如果删除一个蓝图,则会触发useEffect
并记录DEBUG ==> 0
。 / p>
如果setSelected(-1);
背后的想法是取消选择树状视图中的所有蓝图,则可以执行以下操作:
export const BlueprintsProvider = ({ children }) => {
....
const removeSelection = useRef(0);
useEffect(() => {
if (blueprints.length < removeSelection.current) setSelected(-1); // if I removed a blueprint, then fire setSelected(-1);
setCount(blueprints.length);
removeSelection.current = blueprints.length; //removeSelection.current setted as blueprints.length
}, [blueprints]);
当然还要从setSelected(-1);
函数中删除remove
。