Когда переменная с состоянием, которая была создана с использованием useState()
React Hook в компоненте контекста, который я построил, обновляется (используя метод setState()
), один из моих функциональных компонентов, который использует эту переменную, не обновляется. Должна ли эта переменная использоваться непосредственно в функциональном компоненте или передаваться в качестве поддержки от родительского функционального компонента?
Ожидаемое поведение
Пользователь нажимает кнопку, вызывая удаление одного из уведомлений. они установили. Пользовательский интерфейс затем удаляет это уведомление из строки таблицы, отображаемой в пользовательском интерфейсе. Когда уведомлений нет, пользователю предоставляется возможность добавить их. Когда пользователь добавляет уведомление, оно появляется в пользовательском интерфейсе в виде строки таблицы.
Наблюдаемое поведение
Пользователь может удалять уведомления (и это немедленно отражается в таблице), но когда все уведомления удаляются и пользователь пытается добавить одно, оно успешно добавляется в с помощью метода setState()
в компоненте поставщика контекста, но это не приводит к тому, что функциональный компонент, использующий эту переменную через метод useContext()
, обновляет пользовательский интерфейс.
Соответствующие фрагменты кода
Компонент контекста создает переменную alert
и использует функцию редуктора для ее обновления
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;
}
}
Компоновка компоновки компонентов пользовательского интерфейса
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>
);
Дочерний компонент пользовательского интерфейса создает таблицу на основе 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
обновляется в компоненте контекста, пользовательский интерфейс не создается, в частности, AlertTable
Компонент - перерисовать? Должен ли повторный рендеринг быть вызван изменением переменной, используемой useContext()
? - Лучше ли использовать переменную Context непосредственно в компоненте пользовательского интерфейса (например,
AlertTable
) или использовать ее «Выше в дереве компонентов» (например, PersonalAlerts
), а затем передать его как опору дочернему компоненту?
Заранее спасибо за помощь.