reactjs React:钩取代HOC和渲染 prop ?

z9smfwbn  于 2023-01-17  发布在  React
关注(0)|答案(1)|浏览(114)

从React钩子常见问题解答中,我们了解到钩子可以取代返回/渲染单个组件的HOC和渲染 prop 。
我试图更好地理解这一点,以及为什么这是一个事实。
我们先来看看HOC:
HOC是一个函数,它接受一个组件作为参数,将其 Package 在周围的逻辑中,如效果和状态,并返回一个新的组件。定制钩子究竟如何取代它呢?我们仍然需要用其他逻辑 Package 输入函数的函数。
查看渲染 prop :
渲染 prop 是一个组件,我们把它作为 prop 传递给另一个组件,然后另一个组件用一些新的 prop 渲染传递过来的组件。我想我们可以用钩子来代替它,方法是创建一个返回完整组件的自定义钩子,然后在任何需要的组件中使用这个钩子。所以父组件不必把一个组件作为 prop 传递给它的子组件。钩子就是这样代替渲染 prop 的吗?
最好用代码示例来解释钩子如何在最常见的用例中替换HOC和渲染 prop ,这将是非常感谢的。

hujrc8aj

hujrc8aj1#

HOC和render proper有很多不同的用法,所以我不可能一一介绍,但基本上这一段指出了许多使用HOC/render proper的情况也可以通过hook实现。我想说,hook的便利性使其成为大多数希望共享代码的情况下的一个很好的选择。但是我不会说它们使HOC/render props过时,如果你需要你的代码同时使用类和函数组件,那么HOC/render props仍然可以使用;或者如果你有一个情况下,挂钩是笨重的,或者如果你只是平原喜欢他们更好。
HOC/render prop的一个常见任务是管理一些数据的生命周期,并将这些数据传递给派生组件或子组件。在下面的示例中,目标是获取窗口宽度,包括状态管理和事件监听。
HOC版本:

function withWindowWidth(BaseComponent) {
  class DerivedClass extends React.Component {
    state = {
      windowWidth: window.innerWidth,
    }

    onResize = () => {
      this.setState({
        windowWidth: window.innerWidth,
      })
    }

    componentDidMount() {
      window.addEventListener('resize', this.onResize)
    }

    componentWillUnmount() {
      window.removeEventListener('resize', this.onResize);
    }

    render() {
      return <BaseComponent {...this.props} {...this.state}/>
    }
  }
  // Extra bits like hoisting statics omitted for brevity
  return DerivedClass;
}

// To be used like this in some other file:

const MyComponent = (props) => {
  return <div>Window width is: {props.windowWidth}</div>
};

export default withWindowWidth(MyComponent);

渲染 prop 版本:

class WindowWidth extends React.Component {
  propTypes = {
    children: PropTypes.func.isRequired
  }

  state = {
    windowWidth: window.innerWidth,
  }

  onResize = () => {
    this.setState({
      windowWidth: window.innerWidth,
    })
  }

  componentDidMount() {
    window.addEventListener('resize', this.onResize)
  }

  componentWillUnmount() {
    window.removeEventListener('resize', this.onResize);
  }

  render() {
    return this.props.children(this.state.windowWidth);
  }
}

// To be used like this:

const MyComponent = () => {
  return (
    <WindowWidth>
      {width => <div>Window width is: {width}</div>}
    </WindowWidth>
  )
}

最后但同样重要的是,钩子版本

const useWindowWidth = () => {
  const [width, setWidth] = useState(window.innerWidth);
  useEffect(() => {
    const onResize = () => setWidth(window.innerWidth);
    window.addEventListener('resize', onResize);
    return () => window.removeEventListener('resize', onResize);
  }, [])
  return width;
}

// To be used like this:

const MyComponent = () => {
  const width = useWindowWidth();
  return <div>Window width is: {width}</div>;
}

相关问题