I'm trying to create reusable timebar where it accepts a date
as prop and returns two dates, left
and right
(for example ceil or floor dates...potentially have more logic in it).
I'm trying to figure out what the best way to communicate this to a consumer who can associate other components(graphs etc) which will accept a left
and right
date to sync with the timebar.
Parent (passes date to Child1, receives dates and passes them to Child2)
-> Child1 (Child1 would be the timebar I've created, generates LEFT and RIGHT dates based on prop date passed in)
-> Child2 (this requires LEFT and RIGHT dates from Child1)
I've looked at 2 options:
Callback route: Parent passes a date and a callback to update its state for left and right. Then it uses this left, right date for the graph that needs it.
http://jsbin.com/jikoya/edit?js,console,output
OR
Separate ES6 class with logic This would require the parent to instantiate this class and it would return the enhanced left, right dates ready to use. Then add this to state and let it flow to all components.
constructor(props) {
super(props);
this.timebar = new Timebar(new Date('01-16-2016'))
this.state = {
leftDate: this.timebar.leftDate,
rightDate: this.timebar.rightDate
}
}
render(){
return(
<timebarObj={this.timebarObj} />
<graph leftDate={this.state.leftDate} rightDate={this.state.rightDate}/>
)
}
What would be the drawback of doing it this separate class method, would it be a anti-pattern? The benefit I can see is, I can pass a lot more within the prop by sending this whole instance through.
What you are really talking about is controlled vs uncontrolled components... https://reactjs.org/docs/forms.html#controlled-components
If the child is going to keep track of its own state independent of its container it should be uncontrolled. If the parent needs to know about the state of the child than its state should just come from the parent (your second example)
Another option besides your second example is to use "render props":
class Child extends React.Component {
constructor(props) {
super(props);
this.state = {
leftDate: "",
rightDate: ""
}
this.calcDates = this.calcDates.bind(this)
}
componentDidMount(){
this.calcDates(this.props);
}
componentWillReceiveProps(nextProps){
if (nextProps.origDate !== this.props.origDate) {
this.calcDates(nextProps)
}
}
calcDates = (nextProps) => {
console.log("Child: calcDates", nextProps)
const lf = nextProps.origDate + " left date";
const rt = nextProps.origDate + " right date";
this.setState({leftDate: lf, rightDate: rt}, this.sendToParent)
}
render() {
return this.props.children(this.state)
}
}
class Parent extends React.Component {
render() {
return (
<div>
<Child>
{ state => (
JSX that relies on state from child...
)
}
</Child>
</div>
)
}
}