因此我尝试将应用中一些与警报相关的逻辑集中在一个.tsx文件中,该文件需要在许多组件中可用(具体来说,是一个将从许多组件调用的“add alert”函数)。为此,我尝试使用react context使警报逻辑可用,状态(活动警报的数组)存储在App. tsx中。
Alerts.tsx
export interface AlertContext {
alerts: Array<AppAlert>,
addAlert: (msg: React.ReactNode, style: string, callback?: (id: string) => {}) => void,
clearAlert: (id: string) => void
}
[...]
export function AlertsProvider(props: AlertsProps) {
function clearAlert(id: string){
let timeout = props.currentAlerts.find(t => t.id === id)?.timeout;
if(timeout){
clearTimeout(timeout);
}
let newCurrent = props.currentAlerts.filter(t => t.id != id);
props.setCurrentAlerts(newCurrent);
}
function addAlert(msg: JSX.Element, style: string, callback: (id: string) => {}) {
console.log("add alert triggered");
let id = uuidv4();
let newTimeout = setTimeout(clearAlert, timeoutMilliseconds, id);
let newAlert = {
id: id,
msg: msg,
style: style,
callback: callback,
timeout: newTimeout
} as AppAlert;
let test = [...props.currentAlerts, newAlert];
console.log(test);
props.setCurrentAlerts(test);
console.log("current alerts", props.currentAlerts);
}
let test = {
alerts: props.currentAlerts,
addAlert: addAlert,
clearAlert: clearAlert
} as AlertContext;
return (<AlertsContext.Provider value={test}>
{ props.children }
</AlertsContext.Provider>);
}
function App(props: AppProps){
[...]
const [currentAlerts, setCurrentAlerts] = useState<Array<AppAlert>>([]);
[...]
const alertsContext = useContext(AlertsContext);
console.log("render app", alertsContext.alerts);
return (
<AlertsProvider currentAlerts={currentAlerts} setCurrentAlerts={setCurrentAlerts}>
<div className={ "app-container " + (error !== undefined ? "err" : "") } >
{ selectedMode === "Current" &&
<CurrentItems {...currentItemsProps} />
}
{ selectedMode === "History" &&
<History {...historyProps } />
}
{ selectedMode === "Configure" &&
<Configure {...globalProps} />
}
</div>
<div className="footer-container">
{
alertsContext.alerts.map(a => (
<Alert variant={a.style} dismissible transition={false} onClose={a.callback}>
{a.msg}
</Alert>
))
}
{/*<Alert variant="danger" dismissible transition={false}
show={ error !== undefined }
onClose={ dismissErrorAlert }>
<span>{ error?.msg }</span>
</Alert>*/}
</div>
</AlertsProvider>
);
}
export default App;
到目前为止,我只在CurrentItems.tsx中的一个地方调用alertsContext.addAlert
。我还添加了一些控制台语句,以便于调试。控制台中的输出如下所示:
render app Array [] App.tsx:116
XHRGEThttp://localhost:49153/currentitems?view=Error [HTTP/1.1 500 Internal Server Error 1ms]
Error 500 fetching current items for view Error: Internal Server Error CurrentItems.tsx:94
add alert triggered Alerts.tsx:42
Array [ {…}, {…} ] Alerts.tsx:53
current alerts Array [ {…} ] Alerts.tsx:55
render app Array []
因此,我可以看到,在addAlert
函数结束时,currentAlerts
属性似乎已经更新,但随后App.tsx中的控制台语句显示它为空。我对React相对较新,因此我可能对如何使用/ function有一些误解,但我已经断断续续地戳了一天的大部分时间,但没有成功。所以我希望有人能纠正我。
1条答案
按热度按时间carvr3hs1#
App
中的这一行将在组件树中寻找一个位于 * 更高 * 位置的提供者。在App的 * 内部 * 有一个提供者,但这并不重要。由于组件树中没有位于更高位置的提供者,因此App将获得默认值,该值永远不会改变。您需要颠倒组件的顺序,使提供者高于试图Map值的组件,或者由于状态变量已经在App中,您可以直接使用它并删除对useContext的调用: