假设我有以下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
中是always recreated,也是Compo2
,对吗?
如果是这样,由于foo
每次都会收到一个新函数,这是否意味着memo
将无用,因此Nested
将始终被重新渲染?
答案 0 :(得分:1)
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'>
答案 1 :(得分:1)
您可以使用新的钩子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={theFoo}/>
);
};
useCallback将返回回调的记忆版本,只有在其中一个依赖项已更改(在第二个参数中传递)时,该回调的备注版本才会更改 在这种情况下,我们将空数组作为依赖项传递,因此该函数将仅创建一次。
和嵌套组件:
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
答案 2 :(得分:0)
我发现最好的方法是使用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>
)}
/>
);
}