useState()
当在我构建的上下文组件中使用 React Hook 实例化的有状态变量被更新(使用setState()
方法)时,我使用该变量的功能组件之一不会更新。这个变量应该直接在功能组件中使用,还是作为来自父功能组件的道具传递?
预期行为
用户单击一个按钮,触发删除他们设置的通知之一。UI 然后从 UI 中显示的表行中删除该通知。当没有通知时,会向用户显示添加通知的选项。当用户随后添加通知时,它会在 UI 中显示为表格行。
观察到的行为
用户可以删除通知(这会立即反映在表格中),但是当所有通知都被删除并且用户尝试添加一个通知时,它会通过使用setState()
上下文提供程序组件中的方法成功添加,但这并没有导致功能组件通过该useContext()
方法使用此变量来更新 UI。
相关代码片段
上下文组件实例化alert
变量并使用 Reducer 函数对其进行更新
import React, { createContext, useState } from 'react'
import { sampleUser } from '../SampleData'
export const SettingsContext = createContext();
const SettingsContextProvider = props => {
// Instantiates alerts array (via sample data), and establishes the setAlert update method
const [alerts, setAlerts] = useState(importedSampleUser.withoutAlert);
...
/** Reducer function that handles all notification modifications.
* @param {type} string Add, delete, personal, or organizational.
* @param {obj} obj Object containing the details needed to complete the action on the backend.
*/
const updateAlerts = (type, obj) => {
switch (type) {
// Creates an empty array if notificaitons have all been deleted
case "add notification":
if (!alerts.length) {
setAlerts([]);
};
let newAlertArray = alerts;
newAlertArray.push({
id: obj.id,
type: "Birthday",
group: obj.group,
hoursPrior: obj.hoursPrior
});
// Updates the variable consumed by the UI Component
setAlerts(newAlertArray);
break;
case "delete notification":
let withoutAlert = alerts;
withoutAlert = withoutAlert.filter(alert => alert.id !== obj.id);
setAlerts(withoutAlert);
break;
default:
console.log("Oops! No more alert update types available.");
return;
}
}
UI 组件构建布局
const PersonalAlerts = () => {
// Holds basic layout
return (
<div>
<h5>Your Alerts</h5>
{/* Displays a table with a list of notifications the user has set */}
<AlertTable />
</div>
);
子 UI 组件基于alert
从上下文中消耗的变量创建表
const AlertTable = () => {
// Consumes the alerts state from the Context Component
const { alerts, updateAlerts } = useContext(SettingsContext);
// Handles personal alert delete requests.
const deleteAlert = (e, type, id) => {
e.preventDefault();
// Dispatches action to Settings Context
updateAlerts("delete personal", { id });
};
// Builds an element in the table for each alert the user has set.
let tableElements = alerts.map(alert => {
...
return (
<tr key={alert.id}>
{/* Builds alert row for each alert in array received from Context */}
<td>{alert.type}</td>
</tr>
);
});
// Builds a table row to display if there are no personal alerts to display.
const noAlerts = (
<tr>
<td onClick={() => triggerAddNotificationUI()}>Add a notificaiton</td>
</tr>
);
};
问题
- 为什么,当
alerts
在上下文组件中更新有状态变量时,UI——特别是AlertTable
组件——不重新渲染?是否应该通过更改所消耗的变量来触发重新渲染useContext()
? - 更好的做法是直接在 UI 组件中使用 Context 变量(例如
AlertTable
),还是在“组件树的更高位置”使用它(例如PersonalAlerts
),然后将其作为道具传递给子组件?
在此先感谢您的帮助。