首页 > 解决方案 > 将 React 上下文变量作为道具传递与直接在功能组件中使用

问题描述

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>
  );
};

问题

  1. 为什么,当alerts在上下文组件中更新有状态变量时,UI——特别是AlertTable组件——不重新渲染?是否应该通过更改所消耗的变量来触发重新渲染useContext()
  2. 更好的做法是直接在 UI 组件中使用 Context 变量(例如AlertTable),还是在“组件树的更高位置”使用它(例如PersonalAlerts),然后将其作为道具传递给子组件?

在此先感谢您的帮助。

标签: javascriptreactjsreact-hooksrenderuse-context

解决方案


推荐阅读