[英]React - functional components keep re-render when passing functions as props
[英]React memo components and re-render when passing function as props
假设我有这些React组件:
const Compo1 = ({theName}) => {
return (
<Nested foo={() => console.log('Dr. ' + theName)}/>
);
};
const Compo2 = ({theName}) => {
function theFoo() {
console.log('Dr. ' + theName);
}
return (
<Nested foo={theFoo}/>
);
};
和嵌套组件,包含在memo
:
const Nested = React.memo(({foo}) => {
return (
<Button onClick={foo}>Click me</Button>
);
});
在foo
传递的函数总是在Compo1
和Compo2
重新创建 , Compo1
吗?
如果是这样,因为foo
每次都会收到一个新函数,它是否意味着memo
将无用,因此Nested
将永远重新渲染?
您可以使用新的钩子Api(React> = 16.8)来避免重新创建回调函数。
只需使用useCallback钩子。
例如
父组件
import React, { useCallback} from 'react';
const ParentComponent = ({theName}) => {
const theFoo = () => {
console.log('Dr. ' + theName);
}
const memoizedCallback = useCallback(theFoo , []);
return (
<Nested foo={memoizedCallback}/>
);
};
useCallback将返回一个回调的memoized版本,该版本只在其中一个依赖项发生更改时才会更改(在第二个参数中传递)。在这种情况下,我们将空数组作为依赖项传递,因此该函数只会创建一次。
和嵌套组件:
import React, { memo } from 'react';
const Nested = ({foo}) => (
<Button onClick={foo}>Click me</Button>
);
export default memo(Nested);
有关详细信息, 请访问https://reactjs.org/docs/hooks-reference.html#usecallback
memo
功能将浅显比较每个不同的道具,包括功能。 但是,通过在每个渲染中重新定义组件内部的函数,每次都会创建一个不同的引用,从而触发重新渲染。
虽然,正如您在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'>
我找到的最好的方法是使用useRef
。 具体来说,我将此结构与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.