Pass the refs to `getDerivedStateFromProps`?
See original GitHub issueI was wondering if it’s a good idea to pass the refs to getDerivedStateFromProps. I understand why passing the instance is not welcomed, but there are some edge cases where the next state is calculated based on refs.
Take a look at the example below:
const getFlyoutPosition = ({
idealDirection,
margin = parseInt(staticTooltip.margin, 10),
relativeOffset,
triggerRect
}) => {
const windowSize = {
height: window.innerHeight,
width: window.innerWidth,
scrollX: 0,
scrollY: 0
};
// Here `this.flyoutRef` is needed to get the element dimensions and use them to calculate the next state
// At the moment there is no way to access the refs in `getDerivedStateFromProps`
const flyoutSize = {
height: this.flyoutRef ? this.flyoutRef.clientHeight : 0,
width: this.flyoutRef ? this.flyoutRef.clientWidth : 0
};
const mainDir = getMainDir(flyoutSize, idealDirection, triggerRect, windowSize, margin);
const base = baseOffsets(relativeOffset, flyoutSize, mainDir, triggerRect, windowSize, margin);
const flyoutOffset = {
top: base.top,
left: base.left
};
return { flyoutOffset, mainDir };
};
export default class extends Component {
state = {
flyoutOffset: {
top: undefined,
right: undefined,
bottom: undefined,
left: undefined
},
mainDir: null,
};
static getDerivedStateFromProps = getFlyoutPosition
setFlyoutRef = (c) => { this.flyoutRef = c; }
flyoutRef;
render() {
const { flyoutOffset } = this.state;
const { children } = this.props;
return (
<div
ref={this.setFlyoutRef}
style={{ position: 'absolute', ...flyoutOffset }}
>
{children}
</div>
);
}
}
I think we should consider passing refs to getDerivedStateFromProps as sometimes the state may be based on values from the DOM.
Please let me know if I should create a PR.
Issue Analytics
- State:
- Created 5 years ago
- Comments:8 (3 by maintainers)
Top Results From Across the Web
You Probably Don't Need Derived State – React Blog
getDerivedStateFromProps exists for only one purpose. It enables a component to update its internal state as the result of changes in props. Our ......
Read more >React 16.4 enables getDerivedStateFromProps to be called ...
So 16.4 "fixes" a bug in getDerivedStateFromProps and now it gets fired both on props change and on state change. Obviously this is...
Read more >React.js static getDerivedStateFromProps() - GeeksforGeeks
method in both mounting and updating phase in React. It takes updated props and the current state as arguments.
Read more >Concepts of React JS — Part 1 - Anil Kumar - Medium
The state of a parent component can be passed to the child only as a prop. ... Refs provide a way to access...
Read more >React lifecycle methods: An approachable tutorial with examples
static getDerivedStateFromProps is a new React lifecycle method as of React 17 ... it gets passed the previous props and state as arguments....
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found

It’s not clear to me why your code is both reading values from and writing values to a ref in response to a change in external props. I don’t think there’s enough context in the code example above to really understand why that’s important (e.g. what’s
mainDirused for and how isgetMainDirrelated to your component).But I suspect you shouldn’t need to use
getDerivedStateFromPropsfor that. In general, there are usually better solutions thangetDerivedStateFromProps.Jason mentioned the
getSnapshotBeforeUpdatelifecycle, but I’m not sure that’s really needed in this case either.From my limited knowledge of this component, I would be inclined to say that you could just do everything you’re doing in
componentDidUpdate. Something like this:The “correct” way to do this would be to move the state update to
componentDidUpdate, if you need to take measurements before the render,getSnapshotBeforeUpdateis exactly the right tool for the job here