У меня есть несколько компонентов с похожим частичным кодом в методах жизненного цикла и некоторым сходством в переменных состояния. Есть ли способ объединить их, унаследовав от одного родителя или что-то в этом роде?
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
}
Могу ли я использовать дочерние методы и свойства в родительской «оболочке»? Могу ли я изменить состояние компонента из родительского?



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Вы можете создать компонент более высокого порядка (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>
);
Здесь - это полная документация по этой технике.
Спасибо, а как может выглядеть SomeComponent, если это компонент с конструктором, методами, функцией рендеринга ...?
@Jeremy, вы можете легко преобразовать функциональный компонент в состояние с отслеживанием состояния, просто вставьте компонент <HOC> {({state, setState}) => 'something'} </HOC> в результаты функции рендеринга, и все готово
хорошо .. таким образом я не могу использовать setState из HOC внутри lifecircle или других методов SomeComponent, только непосредственно в рендере, верно?
@Jeremy, о, вы можете легко направить этот setState в SomeComponent, в функции рендеринга просто вызовите что-то вроде this.registerHOC ({state, setState}), который будет registerHOC = (({state, setState}) => if (! This. HOCRegistered) {this.HOCSetState = setState; this.HOCState = state; this.HOCRegistered = true}
В этом случае вы можете создать 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?
Нет, но вы можете передать функцию обратного вызова компоненту как опору и вызывать всякий раз, когда это необходимо в дочернем элементе, чтобы обновить что-то в родительском элементе. Я обновлю свой ответ, чтобы отразить это.
Это не совсем HOC, эта техника называется
render props.