状态更改后仅渲染一个 child 组件
Rendering only one child component after state change
我构建了一个包含两个 children 的 React 组件:一个显示图形 (vis.js),当用户将鼠标悬停在图形中的一个节点上时,主要组件会被感知这是由状态变化引起的。唯一使用此状态的 child 是 div(该图的同级)。
但是,当状态发生变化时,所有children(包括图形)都是re-rendered。我不想每次将鼠标悬停在节点上时都渲染图形,只是它的兄弟节点。
这是我的代码:
import React, { useState } from "react";
...
const Graph = (props) => {
...
const [nodeName, setNodeName] = useState("");
function handleHoverEvent(node) {
if (nodeName !== node) {
setNodeName(node);
}
}
function makeNodes() {
...
}
function makeEdges() {
...
}
return (
<div>
<Vis
nodes={makeNodes()}
edges={makeEdges()}
OnHover={handleHoverEvent}
/>
<NameDisplay name={nodeName} />
</div>
);
}
...
export default Graph;
makeNodes()
和 makeEdges()
不以任何方式依赖于状态。
如何防止图表每次都是 re-rendered?我需要做的就是将数据从一个 child“铲”到另一个 child,同时只更新其中一个。
您可以使用 React.memo()
、React.useCallback
来避免在 React 组件中重新渲染内容。 Avoiding React component re-renders with React.memo
示例:
按钮
import React from "react";
interface IProps {
handleClick: () => void;
children: any;
}
function Button({ handleClick, children }: IProps) {
console.log("Rendering button - ", children);
return <button onClick={handleClick}>{children}</button>;
}
export default React.memo(Button);
计数
import React from "react";
import Button from './Button'
interface IProps {
text: any;
count: any;
handleClick: () => void;
children: any;
}
function Count({ text, count, handleClick, children }: IProps) {
console.log(`Rendering ${text}`);
return (
<div>
<div>
{text} - {count}
</div>
<Button handleClick={handleClick}>{children}</Button>
</div>
);
}
export default React.memo(Count);
父组件
import React, { useState, useCallback } from "react";
import Count from "./Count";
export const ParentComponent = () => {
const [age, setAge] = useState(25);
const [salary, setSalary] = useState(50000);
// const incrementAge = () => {
// setAge(age + 1)
// }
// const incrementSalary = () => {
// setSalary(salary + 1000)
// }
const incrementAge = useCallback(() => {
setAge(age + 1);
}, [age]);
const incrementSalary = useCallback(() => {
setSalary(salary + 1000);
}, [salary]);
return (
<>
<Count text="Age" count={age} handleClick={incrementAge}>
Increment Age
</Count>
<Count text="Salary" count={salary} handleClick={incrementSalary}>
Increment Salary
</Count>
</>
);
};
只需将所有组件转换为 ES6 类。此处对此进行了描述:https://reactjs.org/docs/state-and-lifecycle.html#converting-a-function-to-a-class
我什至不必指定 shouldComponentUpdate() 方法。
我构建了一个包含两个 children 的 React 组件:一个显示图形 (vis.js),当用户将鼠标悬停在图形中的一个节点上时,主要组件会被感知这是由状态变化引起的。唯一使用此状态的 child 是 div(该图的同级)。
但是,当状态发生变化时,所有children(包括图形)都是re-rendered。我不想每次将鼠标悬停在节点上时都渲染图形,只是它的兄弟节点。
这是我的代码:
import React, { useState } from "react";
...
const Graph = (props) => {
...
const [nodeName, setNodeName] = useState("");
function handleHoverEvent(node) {
if (nodeName !== node) {
setNodeName(node);
}
}
function makeNodes() {
...
}
function makeEdges() {
...
}
return (
<div>
<Vis
nodes={makeNodes()}
edges={makeEdges()}
OnHover={handleHoverEvent}
/>
<NameDisplay name={nodeName} />
</div>
);
}
...
export default Graph;
makeNodes()
和 makeEdges()
不以任何方式依赖于状态。
如何防止图表每次都是 re-rendered?我需要做的就是将数据从一个 child“铲”到另一个 child,同时只更新其中一个。
您可以使用 React.memo()
、React.useCallback
来避免在 React 组件中重新渲染内容。 Avoiding React component re-renders with React.memo
示例:
按钮
import React from "react";
interface IProps {
handleClick: () => void;
children: any;
}
function Button({ handleClick, children }: IProps) {
console.log("Rendering button - ", children);
return <button onClick={handleClick}>{children}</button>;
}
export default React.memo(Button);
计数
import React from "react";
import Button from './Button'
interface IProps {
text: any;
count: any;
handleClick: () => void;
children: any;
}
function Count({ text, count, handleClick, children }: IProps) {
console.log(`Rendering ${text}`);
return (
<div>
<div>
{text} - {count}
</div>
<Button handleClick={handleClick}>{children}</Button>
</div>
);
}
export default React.memo(Count);
父组件
import React, { useState, useCallback } from "react";
import Count from "./Count";
export const ParentComponent = () => {
const [age, setAge] = useState(25);
const [salary, setSalary] = useState(50000);
// const incrementAge = () => {
// setAge(age + 1)
// }
// const incrementSalary = () => {
// setSalary(salary + 1000)
// }
const incrementAge = useCallback(() => {
setAge(age + 1);
}, [age]);
const incrementSalary = useCallback(() => {
setSalary(salary + 1000);
}, [salary]);
return (
<>
<Count text="Age" count={age} handleClick={incrementAge}>
Increment Age
</Count>
<Count text="Salary" count={salary} handleClick={incrementSalary}>
Increment Salary
</Count>
</>
);
};
只需将所有组件转换为 ES6 类。此处对此进行了描述:https://reactjs.org/docs/state-and-lifecycle.html#converting-a-function-to-a-class
我什至不必指定 shouldComponentUpdate() 方法。