ReactJS 组件将 useMemo 等同于新参数

问题描述 投票:0回答:1

我有下面这段代码(在reactJS中)。基本上它是小部件的一部分,每次数据更新时,“GraphInfo 已更改:”和“GraphData 已更改:”意味着 uhsestate 和 useMemo 被忽略。我基本上想从带有 graphInfo 变量的数据中导出不同的数据。


const BaseGraphOverTime = ({
  module_key,
  data,
  graph_type,
  y,
  strike,
  opt_type,
}) => {
  const [graphData, setGraphData] = useState(data);
  const { globalState } = useGlobal();

  const graphInfo = useMemo(
    () => ({
      y: y,
      strike: strike,
      opt_type: opt_type,
      ticker: globalState.ticker,
      expiration_date: globalState.expiration_date,
    }),
    [y, strike, opt_type, globalState.ticker, globalState.expiration_date]
  );

  useEffect(() => {
    console.log(
      "GraphInfo changed:",
      y,
      strike,
      opt_type,
      globalState.ticker,
      globalState.expiration_date
    );
  }, [y, strike, opt_type, globalState.ticker, globalState.expiration_date]);
  
  useEffect(() => {
    console.log("GraphData changed:", graphData);
  }, [graphData]);

  return null;
};

export default BaseGraphOverTime;

我尝试将 useMemo 和 useState 相互更改,但没有任何帮助。我什至使用数据的 useState 设置父组件。

javascript reactjs react-hooks memoization
1个回答
0
投票

根据要求,这里有更多代码和更多说明。 数据是通过 websocket 接收的(数据被接收并从它们的 id 发送到不同的小部件)。 MemoizedWidget 和 Widget 渲染正确的组件(此处为 BaseGraphOverTime)

const { socket, data, sendMessage, ws_connected } = useWebSocket("wss://.........");
  
const widgetDataReducer = (state, action) => {
  switch (action.type) {
    case "UPDATE_WIDGET_DATA":
     const { dashboard_item_id, newData } = action.payload;
    if (state[dashboard_item_id] && state[dashboard_item_id] === newData) {
        return state; // No change, so return current state
    }
        return {
          ...state,
          [dashboard_item_id]: newData,
        };
      default:
        return state;
    }
  };

  const [widgetData, dispatch] = useReducer(widgetDataReducer, {});
  
  useEffect(() => {
    if (data) {
      console.log("Data received from WebSocket:", data);
      // Here you can set data to global state or handle it as needed
      if (data.type === "stream") {
        //  We distribute the data
        dispatch({
          type: "UPDATE_WIDGET_DATA",
          payload: {
            dashboard_item_id: data.dashboard_item_id,
            newData: data.data,
          },
        });
      }
    }
  }, [data]);
  
  {...}
  
  return (...
    {layout.map((item) => (
        <div className="widget" key={item.i.key} data-grid={item}>
          <MemoizedWidgetComponent
            viewUnlocked={viewUnlocked}
            widget_type={item.i.type}
            module_key={item.i.key}
            onRemoveWidget={handleRemoveWidget}
            data={widgetData[item.i.key]}
          />
        </div>
     ))}
   ...)

这是小部件:

const WidgetComponent = ({
  viewUnlocked,
  module_key,
  widget_type,
  onRemoveWidget,
  data,
}) => {
  const widget_info = WidgetInformation[widget_type];
  const [widgetInfo, setWidgetInfo] = useState({
    x: "strike_price",
    y: "open_interest",
    graph_type: "line",
    horizontal: false,
    exposure_type: "net",
    strike: null,
    opt_type: "call",
  });
  const { globalState, setGlobalState } = useGlobal();

  const Widget = () => {
    const Component = widget_info.module;

    if (!Component) {
      console.log("Component not found");
      return <div>Component not found</div>;
    }

    return (
      <Component
        module_key={module_key}
        data={data}
        {...widget_info.args}
        {...widgetInfo}
      />
    );
  };

const BaseGraphEvolutionHead = (
   ...<FormControl variant="standard">
          <NativeSelect
            value={widgetInfo.opt_type}
            onChange={(e) =>
              setWidgetInfo({ ...widgetInfo, opt_type: e.target.value })
            }
            input={<CustomInput />}
            inputProps={{
              name: "opt_type",
              id: "uncontrolled-native",
            }}
          >
            <option value="call">Call</option>
            <option value="put">Put</option>
          </NativeSelect>
        </FormControl>
 ...)

const HandleDiv = memo(() => {
    const styleRef = useRef({
      cursor: "default",
      width: "calc(100% - 100px)",
    });

    useEffect(() => {
      if (viewUnlocked) {
        styleRef.current = { ...styleRef.current, cursor: "move" };
      } else {
        styleRef.current = { ...styleRef.current, cursor: "default" };
      }
    }, [viewUnlocked]);

    return (
      <div className="widget-header">
        <Grid container rowSpacing={0} columnSpacing={0}>
          <Grid item minWidth="40px" width="40px">
            <CloseButton />
          </Grid>
          <Grid item className="handle" style={styleRef.current}>
            <BaseGraphEvolutionHead
              ticker={globalState.ticker}
              expiration_date={globalState.expiration_date}
            />
          </Grid>
          <Grid item minWidth="40px" width="40px"></Grid>
        </Grid>
      </div>
    );
  });

return (
    <Grid
      container
      spacing={0}
      style={{ height: "100%", width: "100%", userSelect: "none" }}
      direction="column"
    >
      <Grid item height="30px">
        <HandleDiv />
      </Grid>
      <Grid
        item
        height="calc(100% - 30px)"
        width="100%"
        style={{ paddingBottom: "10px", overflow: "auto" }}
      >
        <div className="content">
          <Widget />
        </div>
      </Grid>
    </Grid>
  );
};


const MemoizedWidgetComponent = memo(
  ({ module_key, widget_type, data, viewUnlocked, onRemoveWidget }) => {

    return (
      <WidgetComponent
        viewUnlocked={viewUnlocked}
        widget_type={widget_type}
        module_key={module_key}
        onRemoveWidget={onRemoveWidget}
        data={data}
      />
    );
  },
  (prevProps, nextProps) => {
    // Log differences if the data objects are not equal
    const dataChanged = !isEqual(prevProps.data, nextProps.data);

    return (
      prevProps.viewUnlocked === nextProps.viewUnlocked &&
      prevProps.module_key === nextProps.module_key &&
      prevProps.widget_type === nextProps.widget_type &&
      !dataChanged
    );
  }
);

在 BaseGraphOverTime 中,我尝试将 useEffect 依赖项设置为:

  • [数据] 和其他 [y、opt_type、strike、globalState.expiration_date、globalState.ticker]
  • 数据的 useState 和其他参数的 useState
  • 所有的useMemo
© www.soinside.com 2019 - 2024. All rights reserved.