[英]Child component not re-rendering with updated props
我有一个子组件,它查看并在 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;
它的父组件:
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;
当用户单击下拉菜单时,我将值传回父组件 (Workspace)。 然后这会更新工作区 state,然后我希望重新渲染子组件 - 但事实并非如此。 当我查看日志时,我看到:
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: {...}}
但我没有看到:
>> in useEffect
我只在应用程序第一次运行时看到此日志。 Table 组件确实获得了新的更新道具,但它不会使用这些新数据重新渲染。 我究竟做错了什么?
该组件绝对是重新渲染的(因为这就是 React 的工作方式),但是useEffect
挂钩的执行不会耦合到关联组件的每个渲染(事实上,这就是它的目的)。
你提供了useEffect(() => {}, [])
第二个参数是“依赖”数组。 当它为空时, useEffect
回调只会在组件第一次挂载后立即执行一次。 如果您希望它在某些内容发生变化时再次执行,您需要将更改后的值包含在依赖项数组中。
但是,如果您要使用更改后的值触发某种异步行为,通常只需要这样做。 如果“准备要呈现的数据”只是将其转换为有用的格式,则根本不需要useEffect
挂钩; 该逻辑应在 function 正文中为 go。
useEffect(() => {}, []) 替换旧 React 版本中的 componentDidMount,这意味着它只在 DOM 中安装组件后执行一次。 我想知道在你的情况下你是否真的需要一个 useEffect,如果是这种情况你需要使用一个没有依赖关系数组的 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 }); 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;
解决方案 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;
您的效果没有依赖性,因此它将运行一次,类似于 class 组件的生命周期方法 componentDidMount。 如果您希望它在道具的一部分发生变化时运行,例如您需要它作为依赖项。
useEffect(() => {
console.log(">> in useEffect ");
// prepare the data to render here and render to the multiple HTML Canvases in the DOM
}, [props.workspaceState]);
您应该将父组件的 state 中的 workspaceState 提供给您的子组件。
<Table
enrichedEvents={this.props.enrichedEvents}
workspaceState={this.state.workspaceState}
className="workspace"
parentCallback={this.handleCallback}
></Table>
您以某种方式试图直接改变父组件的 props,我认为从来没有人建议这样做。 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.