【问题标题】:Can I refactor multiple useEffect to single useEffect?我可以将多个 useEffect 重构为单个 useEffect 吗?
【发布时间】:2020-05-16 23:07:47
【问题描述】:

我的状态宽度随着窗口调整大小和 showFilters 的变化而变化,作为道具从 true 变为 false。我想在卸载时删除监听器。因此,我为每个这些条件使用了三个 useState。 那么,我可以做任何重构以在单个 useEffect 中使用所有这些吗?

import React, { useEffect, useRef, useState } from 'react'
import PropTypes from 'prop-types'
import { Icon } from 'antd'

import TrendsChart from './trendsChart'

import styled from '../styled-components'

const Chart = ({ showFilters }) => {
  const [width, setWidth] = useState(null)
  useEffect(() => {
    window.addEventListener('resize', handleWindowResize)
    updateWidth()
  }, [width])
  useEffect(() => {
    setTimeout(updateWidth, 200)
  }, [showFilters])
  useEffect(() => () => {
    window.removeEventListener('resize', handleWindowResize)
  })
  const updateWidth = () => {
    const containerWidth = chartRef.current.clientWidth
    setWidth(Math.floor(containerWidth))
  }
  const handleWindowResize = () => {
    updateWidth()
  }
  const chartRef = useRef()
  function render() {
    return (
      <styled.chart>
        <styled.chartHeader>
          Daily
        </styled.chartHeader>
        <styled.trendsChart id="chartRef" ref={chartRef}>
          <TrendsChart width={width} showFilters={showFilters}/>
        </styled.trendsChart>
        <div>
          <Icon type="dash" />&nbsp;&nbsp;&nbsp;Credit Trend
        </div>
      </styled.chart>
    )
  }
  return (
    render()
  )
}

Chart.propTypes = {
  showFilters: PropTypes.bool.isRequired
}
export default Chart

【问题讨论】:

  • 你能重构吗?是的,你可以。 你应该重构吗?不。问题是,为什么?你为什么要这样做?
  • 钩子的全部意义在于“订阅”/“收听”您想要的那些依赖项(道具)。所以保持它们小而简洁。您唯一可以重构的是您的 removeEventListener 挂钩,而是从您添加事件侦听器的 useEffect 返回一个函数。这将在卸载时调用。这被称为“清理效果”:reactjs.org/docs/hooks-effect.html#effects-with-cleanup

标签: javascript reactjs react-hooks


【解决方案1】:

据我了解是 你的两个 useEffect 可以合并

useEffect(() => {
window.addEventListener('resize',handleWindowResize)
return () => window.removeEventListener('resize',handleWindowResize)
},[width])

据我了解,对于设置超时部分。这不是必需的,因为每次更改宽度(状态)时,react 都会重新渲染。希望能有所帮助。我也是新手。

【讨论】:

    【解决方案2】:

    您应该查看 CONDITIONS,每种效果何时起作用。

    监听器应该安装一次,并进行清理:

    useEffect(() => {
      window.addEventListener('resize',handleWindowResize)
      return () => window.removeEventListener('resize',handleWindowResize)
    },[])
    
    const handleWindowResize = () => {
      const containerWidth = chartRef.current.clientWidth
      setWidth(Math.floor(containerWidth))
    }
    

    注意:[] 作为 useEffect 参数,如果没有此效果,每个渲染

    都有效

    ...应该足够了:

    • handleWindowResize 设置窗口大小变化的宽度;
    • showFilters 导致自动重新渲染

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-12-05
      • 2019-10-18
      • 2019-10-18
      • 1970-01-01
      • 2020-10-22
      • 2020-12-16
      • 2021-05-31
      • 1970-01-01
      相关资源
      最近更新 更多