当前位置: 首页 > 知识库问答 >
问题:

反应备忘录不起作用-我遗漏了什么?

徐英锐
2023-03-14

我正在重构我们的一些组件,因此我尝试合并记忆,因为一些组件可能会使用相同的值重新呈现(例如,热链接图像URL,除非它们相同)。

我有一个简单的组件:

const CardHeader = props => {
    // img is a stringand showAvatar is a boolean but it's always true
    const { ..., showAvatar, img } = props;

    return (
        <CardHeader>
            <ListItem>
                // AvatarImage shouldn't re-render if img is the same as previous
                {showAvatar && <AvatarImage img={img} />
            </ListItem>
        </CardHeader>
    );
}

然后是阿凡达笠美:

const AvatarImage = React.memo(props => {
   console.log("why is this still re-rendering when the img value hasn't changed?");
   const { img } = props;

   return (
        <ListItemAvatar>
            {img ?
                <Avatar src={img} />    
                :
                <Avatar>
                    Some initials
                </Avatar>
            }
        </ListItemAvatar>
    );
});

我还试着传递备忘录的第二个论点:

(prevProps, nextProps) => {
    return true; // Don't re-render!
}

但是console.log仍然每次都显示出来。我显然遗漏了什么,或者不太明白这是怎么回事。这个组件是几个级别下来,但它通过在img如果它是每次可用的,所以我希望它知道,如果img是通过在以前的渲染,它是一样的,它知道不重新渲染它,但出于某种原因真的吗?

谢谢大家。非常感谢。

共有2个答案

艾浩广
2023-03-14

您是否启用了StrictMode?这将导致用记忆的组件发生反应。备注以渲染两次。

更多信息:

  • https://reactjs.org/docs/strict-mode.html
  • 由于严格模式,我的React组件渲染了两次
柯子琪
2023-03-14

好吧,要么show Avatar并不总是true,要么CardHeaderListItem组件神奇地决定是否显示儿童

示例

const { useState, useEffect, memo, createContext, useContext } = React;

const getAvatars = () => Promise.resolve([
{
  src: 'https://i.picsum.photos/id/614/50/50.jpg'
},
{
  src: 'https://i.picsum.photos/id/613/50/50.jpg'
}
])

const Avatar = ({src}) => {
console.log('avatar render');
  return <img src={src} alt="avatar"/>
}

const MemoAvatarToggle = memo(({src}) => {
console.log('memo avatar with \'expression &&\' render');
  return <div>
  {src ? <img src={src} alt="avatar"/> : <div>Test </div>}
  </div>
})

const CardHeader = ({children}) => {
  const luck = Boolean(Math.floor(Math.random() * 1.7));
  
  
  
  return <div>
    {luck && children}
  </div>
}

const ListItem = ({children}) => {
  return <div>
    {children}
  </div>
}

const ShowAvatarContext = createContext()

const App = (props) => {
  const [avatars, setAvatars] = useState([]);
  const [toggle, setToggle] = useState(false);
  const [showAvatar, setShowAvatar] = useContext(ShowAvatarContext);
  
  useEffect(() => {
    let isUnmounted = false;
    let handle = null;
    
    setTimeout(() => {
      if(isUnmounted) {
        return;
      }
      setShowAvatar(true);
    }, 500);
    
    getAvatars()
      .then(avatars => {
        if(isUnmounted) {
          return;
        }
        
        setAvatars(avatars)
      })
    
    const toggle = () => {
      setToggle(prev => !prev);
      handle = setTimeout(toggle, 1000);
      //setShowAvatar(prev => !prev);
    }
    
    handle = setTimeout(toggle, 1000);
    
    return () => {
      isUnmounted = true;
      clearTimeout(handle);
    }
      
  }, []);
 
  return <div>
    <CardHeader>
      <ListItem>
        {showAvatar && avatars.map((avatar, index) => <MemoAvatarToggle key={index} src={avatar.src}/>)}
      </ListItem>
    </CardHeader>
    {toggle ? 1 : 0} 
  </div>
}

const ShowAvatarProvider = ({children}) => {
  const state = useState(false);
  
  return <ShowAvatarContext.Provider value={state}>
      {children}
    </ShowAvatarContext.Provider>
}

ReactDOM.render(
    <ShowAvatarProvider>
        <App/>
    </ShowAvatarProvider>,
    document.getElementById('root')
  );
<script src="https://unpkg.com/react/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<div id="root"></div>
 类似资料:
  • 此代码显示#datepicker输入组件,但单击后,它不会打开。它也不能调用简单的$(“#日期选择器”)。日期选择器();方法请提供一些解决方案。 简单的datepicker()方法带有自己的默认设置,但我在这个方法中进行了自己的自定义。 在div标签中,它是在body标签中定义的,但我已经使它简短。span标签用于嵌入带有日期选择器输入组件的图标。在这种情况下,我使用的是字形压光。但是在那之前,

  • 问题内容: 我刚开始使用Python,却不知道什么是记忆以及如何使用它。另外,我可以举一个简化的例子吗? 问题答案: 记忆有效地指基于方法输入记忆方法调用的结果(“记忆”→“备忘录”→要记忆),然后返回记忆的结果,而不是再次计算结果。你可以将其视为方法结果的缓存。有关更多详细信息,请参见第387页的Cormen等人的《算法简介》(3e)中的定义。 一个简单的示例,使用Python中的记忆来计算阶乘

  • 问题内容: 我试图将onscroll事件处理程序添加到特定的dom元素。看下面的代码: 代码非常简单,如您所见,我想处理div#list滚动。当我运行此示例时,它不起作用。所以我尝试直接在render方法上绑定this._handleScroll,它也不起作用。 因此,我打开了chrome inspector,直接使用以下命令添加了onscroll事件: 它正在工作!我不知道为什么会这样。这是Re

  • 问题内容: 为什么colspan属性在React中不起作用?我创建了呈现以下内容的简单组件: 编辑:解决 这是解决方案。React期望属性名称为 colSpan ,而不是colspan。在浪费了荒谬的时间去发现这个小小的邪恶事实之后,想出了这一点。 问题答案: 来自React的DOM差异文档: 所有DOM属性和属性(包括事件处理程序)都应包含驼峰,以与标准JavaScript样式保持一致。 如果您

  • 好的,我想我最好在这里补充一点,我知道代码看起来不太好,但我认为它会起作用,所以我很高兴你能解释为什么它不仅有效,而且无效。我也很高兴听到你对这个问题的解决办法! 我很难理解为什么下面的代码块似乎没有按照预期工作,我的意思是记忆

  • 如何使用备忘录模式 在 ViewController.swift 里加上下面两个方法: //MARK: Memento Pattern func saveCurrentState() { // When the user leaves the app and then comes back again, he wants it to be in the exact same state