简体   繁体   English

子组件不使用更新的道具重新渲染

[英]Child component not re-rendering with updated props

I have a child component, it looks through and creates Canvas elements in the DOM, then useEffect() draws things to these Canvases:我有一个子组件,它查看并在 DOM 中创建 Canvas 个元素,然后 useEffect() 将内容绘制到这些画布上:

import { useEffect } from "react";

function Table(props) {
  console.log(">> In Table, props is ", props);

  useEffect(() => {
    console.log(">> in useEffect ");

    // prepare the data to render here and render to the multiple HTML Canvases in the DOM
  }, []);

  const options = [
    { value: 0, label: "1" },
    { value: 1, label: "2" }
  ];

  const onChannelXChange = (option) => {
    console.log("1. send the change back to the parent");

    let change = {
      type: "ChannelIndexChange",
      // TODO need to get the plot here
      plotIndex: 0,
      channel: "x",
      value: option.value,
    };
    props.parentCallback(change);
  };

  return (
    <table className="workspace">
      <tbody>
          <tr key={`tr-${fileIndex}`}>
            {props.workspaceState.plots.map((plot, plotIindex) => {
              return (
                <td key={`td-${plotIindex}`}>
                  <div>
                    <canvas
                      className="canvas"
                      id={`canvas-${fileIndex}-${plotIindex}`}
                      width="400"
                      height="400"
                    />
                    <Dropdown
                      options={options}
                      onChange={onChannelXChange}
                      placeholder="Select an option"
                    />
                  </div>
                </td>
              );
            })}
          </tr>
      </tbody>
    </table>
  );
}

export default Table;

And it's parent component:它的父组件:

import Table from "./Table";
import React, { useState } from "react";

class Workspace extends React.Component {
  constructor(props) {
    super();

    this.state = {
      workspaceState: {},
    };

    this.state.workspaceState = props.workspaceState;

    this.handleCallback = this.handleCallback.bind(this);
  }

  handleCallback = (option) => {
    this.props.workspaceState.value = option.value;

    // I expect this to re-render the Table Component with the updated props
    console.log("2. updating state");
    this.setState({ workspaceState: this.props.workspaceState });
  };

  render() {
    return (
      <Table
        enrichedEvents={this.props.enrichedEvents}
        workspaceState={this.props.workspaceState}
        className="workspace"
        parentCallback={this.handleCallback}
      ></Table>
    );
  }
}

export default Workspace;

When the suer clicks on the Dropdown, I pass the value back up to the parent component (Workspace).当用户单击下拉菜单时,我将值传回父组件 (Workspace)。 This then updates the Workspace state, and I then expect the child coponent to be re-rendered - except it is not.然后这会更新工作区 state,然后我希望重新渲染子组件 - 但事实并非如此。 When I look at the logs, I see:当我查看日志时,我看到:

Workspace.js:44 1. send the change back to the parent
Workspace.js:44 2. updating parent state component
Table.js:95 >> props is {workspaceState: {...}}

But I dont see:但我没有看到:

 >> in useEffect

I only see this log the first time the app runs.我只在应用程序第一次运行时看到此日志。 The Table component is indeed getting the new updated props, but it wont re-render with this new data. Table 组件确实获得了新的更新道具,但它不会使用这些新数据重新渲染。 What am I doing wrong?我究竟做错了什么?

The component absolutely is re-rendering (because that's how react works), but execution of a useEffect hook is not coupled to each render of the associated component (in fact, that's its purpose).该组件绝对重新渲染的(因为这就是 React 的工作方式),但是useEffect挂钩的执行不会耦合到关联组件的每个渲染(事实上,这就是它的目的)。

You've provided useEffect(() => {}, [])你提供了useEffect(() => {}, [])

The second argument is the 'dependency' array.第二个参数是“依赖”数组。 When this is empty, the useEffect callback will execute once only , straight after the component first mounts.当它为空时, useEffect回调只会在组件第一次挂载后立即执行一次 If you want it to execute again when something changes, you'll need to include the changed value in the dependency array.如果您希望它在某些内容发生变化时再次执行,您需要将更改后的值包含在依赖项数组中。

You generally only need to do this if you are going to trigger some kind of async behaviour using the changed value however.但是,如果您要使用更改后的值触发某种异步行为,通常只需要这样做。 If 'prepare the data to render' does nothing but transform it into a useful format, you don't need a useEffect hook at all;如果“准备要呈现的数据”只是将其转换为有用的格式,则根本不需要useEffect挂钩; that logic should go in the function body.该逻辑应在 function 正文中为 go。

useEffect(() => {}, []) replace the componentDidMount in old react versions that means it execute only once after mounting the component in DOM. useEffect(() => {}, []) 替换旧 React 版本中的 componentDidMount,这意味着它只在 DOM 中安装组件后执行一次。 I am wondering if you really need a useEffect in your case, if it the case you need to use a useEffect without array of dependencies.我想知道在你的情况下你是否真的需要一个 useEffect,如果是这种情况你需要使用一个没有依赖关系数组的 useEffect。 LIke that:像那样:

 import { useEffect } from "react"; function Table(props) { console.log(">> In Table, props is ", props); useEffect(() => { console.log(">> in useEffect "); // prepare the data to render here }); const options = [ { value: 0, label: "1" }, { value: 1, label: "2" } ]; const onChannelXChange = (option) => { console.log("1. send the change back to the parent"); props.parentCallback(option); }; return ( <Dropdown options={options} onChange={onChannelXChange} placeholder="Select an option" /> ); } export default Table;

Solution 2: As i said am wondering if you really need a useEffect you can directly do it like that解决方案 2:正如我所说,我想知道你是否真的需要一个 useEffect 你可以直接这样做

 import { useEffect } from "react"; function Table(props) { console.log(">> In Table, props is ", props); // put you logic directly here // prepare the data to render here const options = [ { value: 0, label: "1" }, { value: 1, label: "2" } ]; const onChannelXChange = (option) => { console.log("1. send the change back to the parent"); props.parentCallback(option); }; return ( <Dropdown options={options} onChange={onChannelXChange} placeholder="Select an option" /> ); } export default Table;

Your effect has no dependencies, so it will run once, similar life-cycle method componentDidMount of a class component.您的效果没有依赖性,因此它将运行一次,类似于 class 组件的生命周期方法 componentDidMount。 If you want it to run whenever a part of your props change eg you need this as dependency.如果您希望它在道具的一部分发生变化时运行,例如您需要它作为依赖项。

  useEffect(() => {
    console.log(">> in useEffect ");

    // prepare the data to render here and render to the multiple HTML Canvases in the DOM
  }, [props.workspaceState]);

You should provide the workspaceState from state of parent component to your child component.您应该将父组件的 state 中的 workspaceState 提供给您的子组件。

  <Table
    enrichedEvents={this.props.enrichedEvents}
    workspaceState={this.state.workspaceState}
    className="workspace"
    parentCallback={this.handleCallback}
  ></Table>

You are somehow trying to mutate the props of the parent component directly, I don't think this is ever advised.您以某种方式试图直接改变父组件的 props,我认为从来没有人建议这样做。 React will not recognize this and do a re-render. React 不会识别这一点并重新渲染。

  handleCallback = (option) => {
    this.props.workspaceState.value = option.value;

    // I expect this to re-render the Table Component with the updated props
    console.log("2. updating state");
    this.setState({ workspaceState: this.props.workspaceState });
  };

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 将 props 传递给子组件时避免组件重新渲染 - Avoid component re-rendering when passing props to child component 当道具更改时,React 子组件不会重新渲染 - React Child Component not re-rendering when props change 反应子组件不会在更新的父状态上重新渲染 - React child component not re-rendering on updated parent state 在console.log中,状态已更新,也通过道具反映出来,但是该组件未重新呈现 - State is updated, also its reflecting with props, in console.log, however the component is not re-rendering 为什么在更改发送给子组件(react js)的道具的值时会进行组件重新渲染? - Why is a Component Re-Rendering done when changing the value of the props sent to child Component (react js)? 子组件不会随着更改而重新呈现 - Child component not re-rendering with changes 子组件问题的多次重新渲染 - Multiple re-rendering of child component problem 子组件,无限重渲染 - Child component, infinitely re-rendering 修复未重新渲染的子组件的方法(由于数据的更改是作为props而不是状态传递的)? - Ways to fix a child component that is not re-rendering (due to change in data being passed in as props, not state)? 如何在父组件的道具发生变化时停止重新渲染子组件? - How to stop re-rendering of child component when its parent's props change?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM