我有一个问题,一个图像闪烁,因为它是无缘无故地呈现,尽管使用React.memo,尽管它的道具或状态不被改变。
我成功地使用了这里,正确地利用了React.memo,BUUUT,因为一个我不明白的原因,如果我在父组件中使用一个高阶组件,那么备忘录就不再工作了,我又遇到了闪烁的问题。
以下是代码:
import * as React from 'react';
import { Text, View, StyleSheet } from 'react-native';
let interval = null
const Icon = ({ name }) => {
// We emulate a rerender of the Icon by logging 'rerender' in the console
console.log('rerender')
return <Text>{name}</Text>
}
const Memo = React.memo(Icon, () => true)
const withHOC = (Comp) => (props) => {
return <Comp {...props}/>
}
export default function App() {
const [state, setState] = React.useState(0)
const name = 'constant'
// Change the state every second
React.useEffect(() => {
interval = setInterval(() => setState(s => s+1), 1000)
return () => clearInterval(interval)
}, [])
// Remove this line and replace NewView by View to see the expected behaviour
const NewView = withHOC(View)
return (
<NewView>
<Memo name={name} />
</NewView>
);
}
我不明白为什么我的特写打破了回忆录,我不知道如何防止闪烁在我的应用程序,仍然能够使用特别.
发布于 2020-05-06 14:04:52
您正在重新创建您的呈现函数中的临时属性。因此,在呈现之间,该组件的任何子组件都不能保持一致。
如果您将临时创建移出呈现之外,那么它将工作!
const Text = 'span';
const View = 'div';
let interval = null
const Icon = ({ name }) => {
// We emulate a rerender of the Icon by logging 'rerender' in the console
console.log('rerender')
return <Text>{name}</Text>
}
const Memo = React.memo(Icon, () => true)
const withHOC = (Comp) => (props) => {
return <Comp {...props}/>
}
// move it out here!
//
const NewView = withHOC(View)
//
function App() {
const [state, setState] = React.useState(0)
const name = 'constant'
// Change the state every second
React.useEffect(() => {
interval = setInterval(() => setState(s => s+1), 1000)
return () => clearInterval(interval)
}, [])
// Remove this line and replace NewView by View to see the expected behaviour
return (
<NewView>
<Memo name={name} />
</NewView>
);
}
ReactDOM.render(<App />, document.querySelector('#root'));
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>
编辑:我在另一个回答中看到了你的评论。
好的,但是我如何在我的组件中使用临时的呢?因为我需要为专案小组提供道具和州政府.
如果您确实需要在组件中创建自组织,您可以使用useMemo
包装它,因为如果useMemo
的依赖项没有改变,React将保留在呈现之间的特殊引用(注意:如果钩子依赖项在每次呈现时发生变化,这将无法工作)。
function App() {
// ...
const NewView = useMemo(() => withHOC(View), []);
}
虽然这是可行的,但它可能有点不稳定。一般来说,钩子和HOCs不是一起使用的模式。反应核心团队创建了钩子来取代HOCs。在你继续走这条路之前,我想看看你是否可以把你的专案写成一个钩子。我想你会发现这更自然。
发布于 2020-05-06 14:08:54
在每次重呈现时,您都会创建一个新的NewView
,因此旧的(以及您的Icon
)将被销毁。因此,它实际上并不是在Icon
上发生的重呈现,而是一个新 Icon
的全新呈现。
如果您将const NewView = withHOC(View)
移出您的App
函数,您的HOC
将被调用一次,创建一个将用于每次重呈现的NewView
,这将防止您的Icon
也被销毁,并且在您回忆录中,您可以安全地避免不必要的重呈现。
import * as React from 'react';
import { Text, View, StyleSheet } from 'react-native';
let interval = null
const Icon = ({ name }) => {
// We emulate a rerender of the Icon by logging 'rerender' in the console
console.log('rerender')
return <Text>{name}</Text>
}
const Memo = React.memo(Icon, () => true)
const withHOC = (Comp) => (props) => {
return <Comp {...props}/>
}
const NewView = withHOC(View);
export default function App() {
const [state, setState] = React.useState(0)
const name = 'constant'
// Change the state every second
React.useEffect(() => {
interval = setInterval(() => setState(s => s+1), 1000)
return () => clearInterval(interval)
}, [])
// Remove this line and replace NewView by View to see the expected behaviour
return (
<NewView>
<Memo name={name} />
</NewView>
);
}
为了更好地理解正在发生的事情,我在您的这里组件上添加了一个日志NewView
,这样您就可以看到该组件在每个父版本的重新呈现上都会卸载,而它必须通过创建一个全新的NewView
和一个新回忆录Icon
来销毁。
https://stackoverflow.com/questions/61645789
复制相似问题