Передача переменных контекста React в качестве подпорки против потребления непосредственно в функциональных компонентах - PullRequest
2 голосов
/ 13 марта 2020

Когда переменная с состоянием, которая была создана с использованием 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>
  );
};

Вопросы

  1. Почему, когда переменная с состоянием alerts обновляется в компоненте контекста, пользовательский интерфейс не создается, в частности, AlertTable Компонент - перерисовать? Должен ли повторный рендеринг быть вызван изменением переменной, используемой useContext()?
  2. Лучше ли использовать переменную Context непосредственно в компоненте пользовательского интерфейса (например, AlertTable) или использовать ее «Выше в дереве компонентов» (например, PersonalAlerts), а затем передать его как опору дочернему компоненту?

Заранее спасибо за помощь.

...