[英]React memo components and re-render when passing function as props
Suppose I have these React components: 假设我有这些React组件:
const Compo1 = ({theName}) => {
return (
<Nested foo={() => console.log('Dr. ' + theName)}/>
);
};
const Compo2 = ({theName}) => {
function theFoo() {
console.log('Dr. ' + theName);
}
return (
<Nested foo={theFoo}/>
);
};
And the nested component, wrapped in memo
: 和嵌套组件,包含在
memo
:
const Nested = React.memo(({foo}) => {
return (
<Button onClick={foo}>Click me</Button>
);
});
Function passed in foo
is always recreated in Compo1
and also Compo2
, correct? 在
foo
传递的函数总是在Compo1
和Compo2
重新创建 , Compo1
吗?
If so, since foo
receives a new function every time, does it mean memo
will be useless, thus Nested
will always be re-rendered? 如果是这样,因为
foo
每次都会收到一个新函数,它是否意味着memo
将无用,因此Nested
将永远重新渲染?
You can use new hooks Api(React >= 16.8) to avoid recreating callback func. 您可以使用新的钩子Api(React> = 16.8)来避免重新创建回调函数。
Just using useCallback hook for this. 只需使用useCallback钩子。
For eg 例如
Parent component 父组件
import React, { useCallback} from 'react';
const ParentComponent = ({theName}) => {
const theFoo = () => {
console.log('Dr. ' + theName);
}
const memoizedCallback = useCallback(theFoo , []);
return (
<Nested foo={memoizedCallback}/>
);
};
useCallback will return a memoized version of the callback that only changes if one of the dependencies has changed (which passed in the second argument) In this case we pass empty array as dependencies and therefore the function will be created only once. useCallback将返回一个回调的memoized版本,该版本只在其中一个依赖项发生更改时才会更改(在第二个参数中传递)。在这种情况下,我们将空数组作为依赖项传递,因此该函数只会创建一次。
And nested component: 和嵌套组件:
import React, { memo } from 'react';
const Nested = ({foo}) => (
<Button onClick={foo}>Click me</Button>
);
export default memo(Nested);
For more info - https://reactjs.org/docs/hooks-reference.html#usecallback 有关详细信息, 请访问https://reactjs.org/docs/hooks-reference.html#usecallback
The memo
function will shallow compare every different props, including functions. memo
功能将浅显比较每个不同的道具,包括功能。 However, by redefining your function inside your components in every render, you will create a different reference every time, triggering a re-render. 但是,通过在每个渲染中重新定义组件内部的函数,每次都会创建一个不同的引用,从而触发重新渲染。
Although, as your can see in Comp3
, you can still use memo and avoid re-rendering by declaring an external function : 虽然,正如您在
Comp3
看到的那样,您仍然可以使用备忘录并通过声明外部函数来避免重新渲染:
class App extends React.Component { constructor(props) { super(props) this.state = { } } componentDidMount = () => { setInterval(() => { this.setState({ e: true }) }, 2000) } render() { return ( <div> <Compo1 /> <Compo2 /> <Compo3 /> </div> ) } } const Compo1 = () => <Nested foo={() => console.log('Comp1 rendering')} /> const Compo2 = () => { function theFoo() { console.log('Comp2 rendering'); } return <Nested foo={theFoo} /> }; const foo3 = function (text) { console.log('Comp3 rendering ' + text) } const Compo3 = () => <Nested foo={foo3} /> const Nested = React.memo(({ foo }) => { foo('a param') return <div /> }) ReactDOM.render(<App />, document.getElementById('root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script> <div id='root'>
The nicest way I found was to use useRef
. 我找到的最好的方法是使用
useRef
。 Specifically I use this structure together with Formik to prevent re-rendering of a long list of input values. 具体来说,我将此结构与Formik一起使用,以防止重新呈现一长串输入值。
const MyMemoizedGroupList = React.memo(
({
groups,
arrayHelpersRef,
}) => {
// [..] stuff
}
}
function MainComponent() {
const groupsArrayHelpersRef = React.useRef();
return (
<Formik
// [..] stuff
render={({ values }) => (
<Form>
<FieldArray
name="groups"
render={arrayHelpers => {
groupsArrayHelpersRef.current = arrayHelpers;
}}
/>
<MyMemoizedGroupList
groups={values.groups}
arrayHelpersRef={groupsArrayHelpersRef}
/>
{/* [..] stuff */}
</Form>
)}
/>
);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.