-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Remove UNSAFE_componentWillReceiveProps from react-json-tree #1049
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Remove UNSAFE_componentWillReceiveProps from react-json-tree #1049
Conversation
Update JSONTree to a functional component to remove the unsave receive props. The functional component uses a useMemo hook on the theme to avoid creating the theme style unless the theme has changed.
c6db35f
to
68dba97
Compare
@@ -47,133 +46,56 @@ const defaultLabelRenderer = ([label]: (string | number)[]) => ( | |||
); | |||
const noCustomNode = () => false; | |||
|
|||
function checkLegacyTheming(theme: Theme | undefined, props: Props) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Methuselah96 As part of this update I removed support for the deprecated styling methods. Removing these is not strictly required to do in this change (just something that made the code easier to reason about). Since this could be seen as a breaking change I am happy to put this back if desired.
@defunctzombie Looks like there are some type errors:
|
|
@Methuselah96 I looked at the types here and can't make sense of where this error comes from or what the intended behavior is. I did not change any of the Prop types in this PR. The error comes from a miss-match between these two types: https://github.com/reduxjs/redux-devtools/blob/main/packages/react-json-tree/src/types.ts#L54 One being optional for |
Previously, |
Even if I updated JSONNestedNode to set a default for circularCache, that doesn't prevent the error. The issue is that JSONArrayNode props are of type So when JSONArrayNode does The two fixes are:
Preferences? |
Right, if a prop is specified in Option 1 is not preferable because |
I've updated the typescript prop types to reflect allowing undefined. |
@Methuselah96 anything else that I need to do on this PR before it can be merged? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for taking this on! I think there are a few things that still need to be addressed before this can be merged. Also, can you add a changeset that includes a description of the change and notes the breaking change of removing the legacy theming props?
<JSONNode | ||
postprocessValue={postprocessValue} | ||
hideRoot={hideRoot} | ||
styling={styling} | ||
shouldExpandNode={shouldExpandNode} | ||
getItemString={getItemString} | ||
labelRenderer={labelRenderer} | ||
valueRenderer={valueRenderer} | ||
isCustomNode={isCustomNode} | ||
collectionLimit={collectionLimit} | ||
keyPath={hideRoot ? [] : keyPath} | ||
value={postprocessValue(value)} | ||
/> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are we failing to pass-through sortObjectKeys
here? Speaking of which, can we make it match the pattern of the other props by making sortObjectKeys
required in JSONNestedNodeCircularPropsPassedThroughJSONTree
, default it to false
in this component, and remove | undefined
when it's listed in the parameters for getCollectionEntries
and getEntries
?
export type CircularPropsPassedThroughJSONNestedNode = | ||
SharedCircularPropsProvidedByJSONTree & | ||
JSONValueNodeCircularPropsPassedThroughJSONTree & | ||
JSONNestedNodeCircularPropsPassedThroughJSONNestedNode; | ||
JSONNestedNodeCircularPropsPassedThroughJSONNode; | ||
|
||
export type CircularPropsPassedThroughRenderChildNodes = | ||
SharedCircularPropsProvidedByJSONTree & | ||
JSONValueNodeCircularPropsPassedThroughJSONTree & | ||
JSONNestedNodeCircularPropsPassedThroughJSONNestedNode; | ||
JSONNestedNodeCircularPropsPassedThroughJSONNode; | ||
|
||
export type CircularPropsPassedThroughItemRange = | ||
SharedCircularPropsProvidedByJSONTree & | ||
JSONValueNodeCircularPropsPassedThroughJSONTree & | ||
JSONNestedNodeCircularPropsPassedThroughJSONNestedNode; | ||
JSONNestedNodeCircularPropsPassedThroughJSONNode; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we go ahead and get rid of these three types since they're now identical to CircularPropsPassedThroughJSONNode
and just use that everywhere?
const expandableLatest = useRef<boolean>(expandable); | ||
expandableLatest.current = expandable; | ||
const handleClick = useCallback(() => { | ||
if (expandableLatest.current) { | ||
setExpanded((prevValue) => !prevValue); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume the intention of the useRef
is to avoid recreating handleClick
and causing unnecessary re-renders if expandable
changes? I'd rather avoid this if possible since it's discouraged by the React docs. My intuition is that the expandable
prop is not going to change often and when it does, I think it's going to require a re-render anyway so it seems like a premature optimization at the cost of more complicated code.
setExpanded(() => { | ||
return !isCircular ? shouldExpandNode(keyPath, data, level) : false; | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason this is passed as a function into setExpanded
? This seems like it would be equivalent to just calculating it without a function.
// When certain props change, we need to re-compute whether our node should be in an expanded state | ||
useEffect(() => { | ||
setExpanded(() => { | ||
return !isCircular ? shouldExpandNode(keyPath, data, level) : false; | ||
}); | ||
}, [isCircular, data, keyPath, level, shouldExpandNode]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe this would reintroduce the undesired behavior discussed here since shouldExpandNode
is often intended to only indicate whether a node should be expanded on the first render. This was fixed by evaluating shouldExpandNode
for the previous props and the current props and only updating the expanded state if they differ.
We're unfortunately stuck in an awkward situation where this component is partially controlled and it's unclear when shouldExpandNode
should be called. We either need to preserve the previous behavior (which seems difficult if we don't want to keep around a reference to the previous props) or come up with a better solution that avoids the difficulties that arise from a prop that allows for partially controlled state. Feel free to pitch some ideas so we can discuss before putting too much working into a single solution. I'll keep thinking about it myself.
@Methuselah96 @defunctzombie Is any of you still working on it? |
I am not currently working on it. |
I too am not currently working on this. |
i wanna to ask which version has fixed this problem |
It has not been resolved yet, but I am working on a fix that I hope will be released within the next week. |
Reworking of #644 to remove UNSAFE_componentWillReceiveProps which is deprecated in react 17 and likely removed in 18.
Components that used UNSAFE_componentWillReceiveProps are converted to functional components with hooks.