I made a simple state wrapper for a react project I am working on, so I can keep my state at the top component but reason about it at a lower class level.
The example below is very simple, but it works and provides enough of an example of what StateWrapper does, obviously i am using it in reality with a much more complex object at the top state level.
This works even when nesting StateWrapped components, the state always lives at the top level.
I'm not 100% sure that this is the right way to go to be honest, but it seems to work quite nicely so that I can keep a complex component's logic local to its class while still keeping the state at the top level and allowing components to interact with eachother at the top stateful level.
Welcome any feedback, i'm aware it might be a bit of an anti-pattern but i can follow the state down through my classes from the top level in my code easily, and the state all lives at the top component so it debugs nicely in chrome and performs well on my more complex app.
Simple working example is as follows:
import * as React from 'react';
export default class Test extends React.Component {
constructor(...props) {
super(...props)
this.component1 = new WrappedComponent (
props => this.setState({component1: props})
)
this.component2 = new WrappedComponent (
props => this.setState({component2: props})
)
//this one passes some initial props
this.component3 = new WrappedComponent (
props => this.setState({component3: props}),
{...this.props}
)
this.state = {
component1: this.component1.state,
component2: this.component2.state,
component3: this.component3.state,
}
}
render() {
return(
<div>
<this.component1.component
onClick={() => this.component2.setText("component1")} />
<this.component2.component
onClick={() => this.component3.setText("component2")} />
<this.component3.component
onClick={() => this.component1.setText("component3")} />
</div>
);
}
}
class StateWrapper {
constructor(setState, initialProps = []) {
this.setState = props => {
this.state = {...this.state, ...props}
setState(this.state)
}
this.props = initialProps
}
render() {
return(<div>render() not defined</div>)
}
component = props => {
this.props = {...this.props, ...props}
return this.render()
}
}
class WrappedComponent extends StateWrapper {
constructor(...props) {
super(...props)
this.state = {
text: "no text has been set"
}
}
render() {
let text = `Received text: ${this.state.text}`
return(
<div onClick={this.onClick}>{text}</div>
)
}
onClick = () => {
this.setState({text: "i got clicked!"})
this.props.onClick()
}
setText = name => this.setState({text: `${name} set my text`})
}