menu

React

A community of developers, designers and others who love React.js. ⚛️

Channels
Team

Passing down props to compute some value and lift the value to parent's state

December 3, 2018 at 3:31pm

Passing down props to compute some value and lift the value to parent's state

December 3, 2018 at 3:31pm (Edited 10 months 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 width
this.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

like-fill
1
  • reply
  • like

@sha-un - 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.

Edited
  • reply
  • like

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.

like-fill
1
  • reply
  • like

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 :)

Edited
  • reply
  • like

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.

like-fill
1
  • reply
  • like

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 @sha-un :))

like-fill
1
  • reply
  • like