Passing down props to compute some value and lift the value to parent's state
December 3, 2018 at 3:31pmPassing down props to compute some value and lift the value to parent's state
December 3, 2018 at 3:31pm (Edited 2 years ago)I don't know why but it bothers me when I write code that follows this pattern, but never found anything to read about that, maybe it is not a problem after all but it doesn't just don't feel right.
class Parent extends React.Component {setWidth = width => this.setState({width})render () {return (<div style={{width: this.state.width}}>...SomeMarkup...<Child setWidth={this.setWidth} {...bunchOfPropsUsedOnTheCalculation} /></div>)}}class Child extends React.PureComponent {calculate(bunchOfPropsUsedOnTheCalculation) {// calculates de widththis.props.setWidth(width)}render () {// render something that also would impact in the calculation}}
maybe there's nothing wrong with that, but it feels that it is wasting resources (more renders) since the calculation could have been made on the parent itself.
December 3, 2018 at 10:41pm
Unless the value of the derived state that the child component is determining is required in sibling components or for use in the parent itself I'm not sure you would need this. Here you pass a function from the parent to be used in the child which then returns a value back to the parent which then could potentially cause another re-render of the child. There is a pattern that uses refs that might be something you could opt into: https://reactjs.org/docs/refs-and-the-dom.html#exposing-dom-refs-to-parent-components
- in the actual code there is a sibling that uses that computed state.
On my example the parent uses it.
That is what I was looking for, thanks for the link!
O the real tree the Child component lifts
width
and height
that are stored on the Parent and is used on its Sibling.Differently from the article, we're not accessing the child's DOM node, instead we send the data used on the computation.
So the data flow is something like that:
Parent
--- { isBold, isItalic, textContent } --> Child
(getBoundingRect of own refs)--{width, height}--> Parent
--{width, height}---> Sibling
This width and height are used as proportion references on the parent, that calculates (with the given
fontSize
) what should be the Sibling
's width and height (just to put some meaning into that)I guess it doesn't breaks encapsulation on the way they describes on that article because the parent doesn't access a child's Node directly but it is a sort of breaking encapsulation.
ya that helps to clarify things a bit :-)
From what I undertand from the article is that you could opt into ref sharing if you wanted to perform the child calc, in your case
getBoundingRect
directly from the parent component and then that could be shared however you like, for instance with the siblings like in your example. It does, like you said, break encapsulation which is a drawback because you would always have a hard dependency on the parent/child relationship to expose data to siblings.Yeah.. so it is a matter of deciding which encapsulation we want to break based on these 2 solutions, hehe
I thought of 2 alternate solutions:
- Have HOC that calculates the width and passes down via props the width and height.
- Create a function `computeRelativeSize` that manipulates the dom and call it on the render of the parent to calculate the the { width, height } that will be used on the following calculations
I have sympathy for the HOC solution but I don't think the function solution is worse than what we have now :)
ya its not released yet, and I'm sure you've heard about Hooks but you might want to keep it in mind for future revisions. https://reactjs.org/docs/hooks-custom.html as you would be able to create your own custom hook that performs the calculations and you can share that between components.
Yep, I guess we are all looking forward for Hooks aren't we? hehe
I'm waiting for the official release but been reading articles around.
I guess by using useRef + useLayoutEffect would be the way to go
(https://reactjs.org/docs/hooks-reference.html#useref, https://reactjs.org/docs/hooks-reference.html#uselayouteffect)
btw - thanks for the conversation :))