Реагируйте: заменяют ли крюки HOC и делают ли реквизиты? - PullRequest
2 голосов
/ 03 июня 2019

Из React Hooks FAQ мы узнаем, что хуки могут заменить HOC и Render Props, которые возвращают / рендерит один компонент.

Я пытался понять это немного лучше, ипочему это факт.

Давайте сначала посмотрим на HOC:

HOC - это функция, которая принимает компонент в качестве аргумента, оборачивает его в окружающую логику, такую ​​как эффекты и состояние, и возвращаетновый компонент.Как именно пользовательский крюк заменит это?Нам по-прежнему нужна функция, которая обертывает входную функцию с другой логикой.

Глядя на реквизиты рендеринга:

Рендеринг реквизита - это компонент, который мы передаем как реквизит другому компоненту, который затем рендеритпередал компонент с некоторыми новыми реквизитами.Я предполагаю, что мы можем заменить это хуками, создав пользовательский хук, который возвращает полный компонент, а затем использовать этот хук в любом необходимом компоненте.Таким образом, родитель не должен передавать компонент как опору своему ребенку.Это то, как хуки заменили бы рендер-реквизиты?

Было бы очень полезно получить объяснение, желательно с примерами кода, о том, как хуки могут заменять HOC и рендеринг-реквизиты в их наиболее распространенных случаях использования.

1 Ответ

3 голосов
/ 03 июня 2019

Существует много различных применений HOC и рендеринга, поэтому я не могу охватить их все, но в основном этот абзац указывает на то, что многие случаи, когда вы используете HOC / рендер, также могут быть достигнуты.с крючкамиЭто не делает устаревшие объекты HOC / рендеринга устаревшими, но ловушки - это еще один инструмент в вашем распоряжении для совместного использования кода между компонентами.

Одной из распространенных задач поддержки HOC / рендера является управление жизненным циклом некоторых данных и передачаэти данные для производного компонента или дочернего компонента.В следующем примере цель состоит в том, чтобы получить ширину окна, включая управление состоянием и прослушивание событий, связанных с этим.

Версия 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() {
      <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);

Версия поддержки рендеринга:

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>;
}
...