reactjs - 将事件处理程序传递给嵌套功能组件时如何避免重新渲染

标签 reactjs

假设我有一个简单的功能组件,它根据过滤器字段呈现许多其他功能组件。 HomeView是父功能组件,它使用状态来处理 DomainCard (子功能组件)过滤:

const HomeView = props => {
  // domains
  const domains = useSelector(state => state.domains)
  const [nameFilter, setNameFilter] = useState('')

  const goToDomainDetailView = id => {
    history.push(config.urls.domainLocal.replace(':id', id))
  }

  return (
    <div>
      <div style={{ marginTop: '2rem', marginBottom: '2rem' }}>
        <Input
          icon='search'
          placeholder='Search domain'
          onChange={(e, { value }) => setNameFilter(value)}
        />
      </div>
      <div>
        {domains.data
          .filter(domain => !nameFilter || domain.name.toLowerCase().includes(nameFilter.toLowerCase()))
          .map((domain, idx) => (
            <div key={idx}>
                <DomainCard
                  fluid
                  raised
                  onClick={goToDomainDetailView}
                  id={domain.id}
                  title={domain.name}
                  image={DomainAutomotiveImage}
                />
            </div>
          ))}
      </div>
      </Container>
    </div>
  )
}

现在这里发生的事情是,在过滤时,已经显示的组件( DomainCard )会重新渲染,即使是内存它们。那是因为HomeView组件本身由于其状态变化而重新呈现,并且作为功能组件,goToDomainDetailView函数被重新定义,并且与之前的提交相比发生了变化。

所以我唯一想到的就是定义 goToDomainDetailView组件外部:

const goToDomainDetailView = id => {
  history.push(config.urls.domainLocal.replace(':id', id))
}

const HomeView = props => {
  // domains
  const domains = useSelector(state => state.domains)
  const [nameFilter, setNameFilter] = useState('')

  return (
    <div>
      <div style={{ marginTop: '2rem', marginBottom: '2rem' }}>
        <Input
          icon='search'
          placeholder='Search domain'
          onChange={(e, { value }) => setNameFilter(value)}
        />
      </div>
      <div>
        {domains.data
          .filter(domain => !nameFilter || domain.name.toLowerCase().includes(nameFilter.toLowerCase()))
          .map((domain, idx) => (
            <div key={idx}>
                <DomainCard
                  fluid
                  raised
                  onClick={goToDomainDetailView}
                  id={domain.id}
                  title={domain.name}
                  image={DomainAutomotiveImage}
                />
            </div>
          ))}
      </div>
      </Container>
    </div>
  )
}

现在,在这种情况下,这个东西可以工作了。

但它有效,因为 goToDomainDetailView例如,函数不依赖于组件 props 或 Redux 调度函数。如果是这种情况,我根本无法将函数移到外面,而我想象的避免重新渲染的唯一其他方法是转换 HomeView Component 类中的组件,因此 goToDomainDetailView函数可以定义为类方法,但在重新渲染时不会改变。

所以问题是:

  • 我的假设正确吗?
  • 您如何处理这种常见情况?
  • 在您看来,这是使用带有状态的嵌套功能组件并避免重新渲染所有功能子组件的正确方法(例如使用 React.memo 的第二个参数并避免重新渲染,如果只有处理程序函数 ref变化?)。

最佳答案

您可以使用 useCallback() Hook 来内存回调:

...
const somePropDependantCallback = useCallback(
  id => console.log(id, someProp),
  [ someProp ]
);

关于reactjs - 将事件处理程序传递给嵌套功能组件时如何避免重新渲染,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58394232/

相关文章:

javascript - 如何在react-native中动态加载模块?

reactjs - 当您需要在仍在从父组件获取数据的情况下渲染某些内容时,最佳实践是什么?

reactjs - 属性 `href` 不匹配。 Next.js 中的服务器

node.js - 如何将 Facebook 身份验证添加到我的 React 应用程序中?

javascript - 如何在 Next JS 中将一个组件(页面)用于多个路由

javascript - 安装后以编程方式关注表单元素

node.js - 放大初始化错误 - ✖ 根堆栈创建失败初始化失败 TypeError : Cannot redefine property: default

javascript - 如何在 JavaScript 中具体格式化日期?

reactjs - 顺风 CSS :before pseudo class

javascript - 检查 Typescript 中的默认值