使用 setState 时反应状态不变
React state not changing, when using setState
我试图让一个开关在用户与之交互时变为 enabled/disabled。这是通过使用 onChange
事件完成的,该事件随后会更改上下文统计信息 key, value
但是,当控制台记录输出时。状态好像没有变化。
上下文是以下值的对象,默认情况下所有值为空。
更新后的上下文:
newSettings:
anti_scam:
enabled: null
log_channel: null
punishment_type: null
tmpSettings 对象
newSettings:
anti_scam:
enabled: true
log_channel: null
punishment_type: null
如您所见,enabled
的值已更改。但是反应上下文状态不是。这意味着该开关始终处于禁用状态或启用状态,具体取决于用户设置,并且他们无法更改它。
我试过的
最初我使用的是可变对象。但后来我发现有时这不会导致重新呈现页面的反应。所以,我转而制作一个不可变副本,并修改我希望从中更改的值。但这仍然没有解决问题。
非常感谢任何帮助。
const EnableSwitch = () => {
const { context, setSaveEnabled } = useContext(SaveContext);
const handleChange = (event) => {
const tmpSettings = JSON.parse(JSON.stringify(context));
tmpSettings.newSettings.anti_scam.enabled = event.target.checked;
setSaveEnabled(tmpSettings);
};
return (
<Fade bottom>
<div>
<Switch
checked={context.newSettings.anti_scam.enabled}
onChange={handleChange}
inputProps={{ "aria-label": "controlled" }}
/>
</div>
</Fade>
);
};
<SaveContext.Provider value={{ context, setSaveEnabled }}>
import { createContext } from "react";
const SaveContext = createContext({
context: {
saveEnabled: false,
oldSettings: {
anti_scam: {
enabled: null,
log_channel: null,
punishment_type: null,
}
},
newSettings: {
anti_scam: {
enabled: null,
log_channel: null,
punishment_type: null,
}
}
},
setSaveEnabled: () => { }
});
export const SaveProvider = SaveContext.Provider;
export default SaveContext;
上下文是一种从组件 A 到组件 B 获取值的方法,但它不会为您实现任何其他功能。如果您想将状态从组件 A 传递到组件 B,那么组件 A 将需要使用 useState
和其他此类代码来实现该状态。由于您只是使用默认值,因此 none 正在发生。
所以你需要在树的顶部附近制作一个组件,如下所示:
const Example = ({ children }) => {
const [state, setState] = useState({
saveEnabled: false,
oldSettings: {
anti_scam: {
enabled: null,
log_channel: null,
punishment_type: null,
},
},
newSettings: {
anti_scam: {
enabled: null,
log_channel: null,
punishment_type: null,
},
},
});
const contextValue = useMemo(() => {
return {
context: state,
setSaveEnabled: /* some function which updates the state */,
}
}, [state]);
return (
<SaveContext.Provider value={contextValue}>
{children}
</SaveContext.Provider>
)
};
我试图让一个开关在用户与之交互时变为 enabled/disabled。这是通过使用 onChange
事件完成的,该事件随后会更改上下文统计信息 key, value
但是,当控制台记录输出时。状态好像没有变化。
上下文是以下值的对象,默认情况下所有值为空。 更新后的上下文:
newSettings:
anti_scam:
enabled: null
log_channel: null
punishment_type: null
tmpSettings 对象
newSettings:
anti_scam:
enabled: true
log_channel: null
punishment_type: null
如您所见,enabled
的值已更改。但是反应上下文状态不是。这意味着该开关始终处于禁用状态或启用状态,具体取决于用户设置,并且他们无法更改它。
我试过的 最初我使用的是可变对象。但后来我发现有时这不会导致重新呈现页面的反应。所以,我转而制作一个不可变副本,并修改我希望从中更改的值。但这仍然没有解决问题。
非常感谢任何帮助。
const EnableSwitch = () => {
const { context, setSaveEnabled } = useContext(SaveContext);
const handleChange = (event) => {
const tmpSettings = JSON.parse(JSON.stringify(context));
tmpSettings.newSettings.anti_scam.enabled = event.target.checked;
setSaveEnabled(tmpSettings);
};
return (
<Fade bottom>
<div>
<Switch
checked={context.newSettings.anti_scam.enabled}
onChange={handleChange}
inputProps={{ "aria-label": "controlled" }}
/>
</div>
</Fade>
);
};
<SaveContext.Provider value={{ context, setSaveEnabled }}>
import { createContext } from "react";
const SaveContext = createContext({
context: {
saveEnabled: false,
oldSettings: {
anti_scam: {
enabled: null,
log_channel: null,
punishment_type: null,
}
},
newSettings: {
anti_scam: {
enabled: null,
log_channel: null,
punishment_type: null,
}
}
},
setSaveEnabled: () => { }
});
export const SaveProvider = SaveContext.Provider;
export default SaveContext;
上下文是一种从组件 A 到组件 B 获取值的方法,但它不会为您实现任何其他功能。如果您想将状态从组件 A 传递到组件 B,那么组件 A 将需要使用 useState
和其他此类代码来实现该状态。由于您只是使用默认值,因此 none 正在发生。
所以你需要在树的顶部附近制作一个组件,如下所示:
const Example = ({ children }) => {
const [state, setState] = useState({
saveEnabled: false,
oldSettings: {
anti_scam: {
enabled: null,
log_channel: null,
punishment_type: null,
},
},
newSettings: {
anti_scam: {
enabled: null,
log_channel: null,
punishment_type: null,
},
},
});
const contextValue = useMemo(() => {
return {
context: state,
setSaveEnabled: /* some function which updates the state */,
}
}, [state]);
return (
<SaveContext.Provider value={contextValue}>
{children}
</SaveContext.Provider>
)
};