因此,我使用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>
);
};
然后我在组件中使用remove函数,如下所示。
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图标时,该项目将从列表中删除,但所选值不会更新为-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]);
没有记录任何内容。
我试图从select
功能中删除setSelected(index);
,当我单击IoMdClose
图标时,selected
将被设置为-1,并使用Effect日志DEBUG ==> -1
。
但现在您有另一个问题:如果您从select
中删除setSelected(index);
,并尝试从左树视图中选择一个蓝图,则蓝图将不会被选择。所以我在select
函数中重新添加了setSelected(index);
。从remove
函数中删除了setSelected(-1);
,现在useEffect不记录任何内容!
我认为发生这种情况是因为您试图将selected
设置为一个不存在的索引(因为您在单击图标时删除了蓝图(。为了验证这一点,我将select
函数中的setSelected(index);
修改为setSelected(0);
,现在生效,如果我删除一个蓝图,useEffect
将被触发并记录DEBUG ==> 0
。
如果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]);
当然,从remove
函数中删除setSelected(-1);
。