Вам нужно использовать хук useCallback
для создания вашего createNotification
императивного обработчика.В противном случае вы создадите новую функцию при каждом рендеринге компонента Notifications
, что приведет ко всем компонентам, потребляющим ваш контекст, для повторного рендеринга, потому что вы всегда передаете новый обработчик всякий раз, когда добавляете уведомление.
Также выскорее всего, это не означает распространение newNotification
в массив уведомлений.
Следующее, что вам нужно сделать, это предоставить версию обратного вызова средства обновления для setState внутри setNotifications
.Он получает текущий список уведомлений, которые вы можете использовать и добавлять новый.Это делает ваш обратный вызов независимым от текущего значения состояния уведомления.Обновление состояния на основе текущего состояния, как правило, является ошибкой без использования функции средства обновления, так как программа реагирует на несколько обновлений.
const Notifications = props => {
const [notifications, setNotifications] = useState([]);
// use the useCallback hook to create a memorized handler
const createNotification = useCallback(
newNotification =>
setNotifications(
// use the callback version of setState
notifications => [...notifications, newNotification],
),
[],
);
const NotificationElems = notifications.map((notification, index) => <Notification key={index} {...notification} />);
return (
<NotificationContext.Provider value={createNotification}>
<React.Fragment>
{NotificationElems}
{props.children}
</React.Fragment>
</NotificationContext.Provider>
);
};
Другая проблема заключается в условном вызове ловушки useContext
, которая не разрешена, Крючки должны называться безоговорочно :
const OtherComponent = () => {
// unconditiopnally subscribe to context
const createNotification = useContext(NotificationContext);
console.log('Re-rendered');
return <button onClick={() => createNotification({text: 'foo'})}>foo</button>;
};
Полностью рабочий пример: