React useState setter不会更新上下文中的值



因此,我使用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);

相关内容

  • 没有找到相关文章

最新更新