React - способ унификации, если многие компоненты имеют один и тот же фрагмент кода в методах жизненного цикла

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

constructor(props) {
    super(props);
    this.state = {
        //state properties similar in all components, getting from redux
        //state properties specific for this component
    }
    // same code in many components
}

componentWillMount() {
    // same code in many components
    // code specific for this component
}

Могу ли я использовать дочерние методы и свойства в родительской «оболочке»? Могу ли я изменить состояние компонента из родительского?

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
4
0
1 223
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы можете создать компонент более высокого порядка (HOC) для этого, в основном, вы просто пишете компонент с тем же методом жизненного цикла, который повторяется, а затем в функции render() вызываете функцию this.props.children с любыми аргументами внутреннего состояния HOC, которые вы хотите, вы можете передать все state и setState также работают, поэтому вы можете изменить состояние HOC внутри базового компонента.

Например:

  class HOC extends React.Component {
   constructor(props) {
     super(props);
     state = {
       someState: 'foo',
     };
   }

   componentWillMount() {
     console.info('i mounted!')
   }
   render() {
     return (
       <div>
         {this.props.children({ state: this.state, setState: this.setState })}
       </div>
     )
   }
 }

 const SomeComponent = () =>
   <HOC>
     {({ state, setState }) => (
       <div>
         <span>someState value: </span>
         <input 
           value = {state.someState} 
           onChange = {e => setState({ someState: e.target.value})} 
         />
       </div>
     )}
   </HOC>

Вы также можете делать с ним действительно крутые и интересные вещи, например, подключать кусочек вашего состояния redux всякий раз, когда вам это нужно:

import { connect } from 'react-redux';

const ProfileState = connect(
  state => ({ profile: state.profile }),
  null,
)(({ 
  profile, 
  children
  }) => ( 
  <div>
    {children({ profile })}
  </div>
));

const ProfilePage = () => (
  <div>
    Your name is:
    <ProfileState>
     {({ profile }) => (
       <span>{profile.name}</span>
     )}
    </ProfileState>
  </div>
);

Здесь - это полная документация по этой технике.

Это не совсем HOC, эта техника называется render props.

Hinrich 07.06.2018 13:06

Спасибо, а как может выглядеть SomeComponent, если это компонент с конструктором, методами, функцией рендеринга ...?

Anna 07.06.2018 14:57

@Jeremy, вы можете легко преобразовать функциональный компонент в состояние с отслеживанием состояния, просто вставьте компонент <HOC> {({state, setState}) => 'something'} </HOC> в результаты функции рендеринга, и все готово

Ilya Lopukhin 07.06.2018 19:11

хорошо .. таким образом я не могу использовать setState из HOC внутри lifecircle или других методов SomeComponent, только непосредственно в рендере, верно?

Anna 08.06.2018 11:12

@Jeremy, о, вы можете легко направить этот setState в SomeComponent, в функции рендеринга просто вызовите что-то вроде this.registerHOC ({state, setState}), который будет registerHOC = (({state, setState}) => if (! This. HOCRegistered) {this.HOCSetState = setState; this.HOCState = state; this.HOCRegistered = true}

Ilya Lopukhin 08.06.2018 16:48
Ответ принят как подходящий

В этом случае вы можете создать HOC (компоненты более высокого порядка). Это может выглядеть так:

/*
   A Higher Order Component is a function,
   that takes a Component as Input and returns another Component.

   Every Component that gets wrapped by this HOC
   will receive `exampleProp`,`handleEvent`, 
   plus all other props that get passed in.
*/

function WithCommonLogic(WrappedComponent) {
  return class extends React.Component {
    constructor(props) {
      super(props);
      this.state = {
        example: ''
      }
    }
    componentWillMount() {
      ...
      // Same code in many components.
    }
    callback = () => {
      /* Enhanced components can access this callback 
         via a prop called `handleEvent`
         and thereby alter the state of their wrapper. */
      this.setState({example: 'some val'})
    }
    render() {
      return <WrappedComponent 
          exampleProp = {this.state.example}
          handleEvent = {this.callback}
          {...this.props}
      />
  }
}


// You use it like this:

const EnhancedComponent1 = WithCommonLogic(SomeComponent);
const EnhancedComponent2 = WithCommonLogic(SomeOtherComponent);

Теперь вся общая логика переходит в этот HOC, который затем обертывает все ваши различные компоненты, с которыми вы хотите им поделиться.

См. React Docs для дальнейшего чтения.

Могу ли я использовать свойства SomeComponent в оболочке WithCommonLogic?

Anna 07.06.2018 15:07

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

Hinrich 07.06.2018 16:45

Другие вопросы по теме