Skip to content
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

Fix - using the new useWindowDimensions api to fix unmounting issues #688

Closed
wants to merge 2 commits into from

Conversation

joe-brabben
Copy link

Overview

Unmounting causes issues with the removal of the event listener so I have used the new useWindowDimensions hook to remove the need for a listener all together as the height and width are got dynamically now.

Test Plan

I ran yarn lint and prettify for code structure testing and tested the modal works on differing screen sizes using android studio.

src/Modal.js Outdated
@@ -106,7 +85,8 @@ export class Modal extends Component {
backdropStyle,
...otherProps
} = this.props;
const { deviceHeight, deviceWidth, isVisible } = this.state;
const { isVisible } = this.state;
const { height, width } = useWindowDimensions();
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this will work because hooks can't be used in class components.

@mmazzarolo
Copy link
Owner

Thanks for working on it! I added a comment

@joe-brabben
Copy link
Author

@mmazzarolo must have worked from a cache issue yeah sorry must have missed this. I'll change it to a functional component now :)

@joe-brabben
Copy link
Author

@mmazzarolo re-done to lint standards and I tested it locally again but let me know if there's anything else to do.

Copy link
Owner

@mmazzarolo mmazzarolo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for you changes 👍 I added a bunch of comments. Let me know if you want me to jump in and make them for you (as soon as I have some free time).

onHide,
...otherProps
}) => {
const animVal = new Animated.Value(0);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be a ref. See the Animated documentation.

Suggested change
const animVal = new Animated.Value(0);
const animVal = useRef(new Animated.Value(0)).current;

const animVal = new Animated.Value(0);
const { state, setState } = useState({
isVisible: isVisible,
isMounted: false,
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we move this to a ref as well? We shouldn't keep this info in the state, we don't want to trigger a re-render when we update it.

...otherProps
}) => {
const animVal = new Animated.Value(0);
const { state, setState } = useState({
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't ran this code yet, but I don't think this should work. useState returns a tuple, so it should be const [state, setState] = useState(blabla). Also, let's track each state variable separately (see the suggestion).

Suggested change
const { state, setState } = useState({
// I'll use a different name variable to not override the one from the props, but ideally I would instead rename the prop one
const [_isVisible, _setIsVisible] = useState(isVisible);

setState({
...state,
isMounted: true,
});
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By using a ref for isMounted we'll be able to avoid this double render.

}

return () => {
setState({
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And we'll avoid this one too, which btw wouldn't work here since the component is being unmounted in this flow, right?

isMounted: true,
});
if (state.isVisible) {
setState({ isVisible: true });
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, I'm missing something here. If the state is already visibile, why are why setting it again to true? 🤔

toValue: 0,
}).start(() => {
if (state.isMounted) {
setState({ isVisible: false }, onHide);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think onHide will be invoked here. setState doesn't have a callback parameter as far as I know.

@joe-brabben
Copy link
Author

hey sorry yeah missed lots here, sorry working on multiple things right now but I am sorting it now. :)

@khzouroussama
Copy link

Hi, is this PR still active? I would love to help accelerate this

@joe-brabben
Copy link
Author

Hi, is this PR still active? I would love to help accelerate this

Hi sorry currently my ability to test the branch has broken. Is there any chance you could pick these changes up when you have time as I wouldn't like to push untested code. Sorry should have kept you updated just been trying to fix the testing issues. Thanks

@khzouroussama
Copy link

khzouroussama commented Mar 15, 2023

No worries @joe-brabben i ll pick this up

@mmazzarolo i have a question, this could've been fixed using Dimentions.addEventListener (https://reactnative.dev/docs/dimensions#addeventlistener) or do you want to refactor the library to functional components?

@mmazzarolo
Copy link
Owner

@khzouroussama I think any solution is fine as long as we solve the issue without using deprecated APIs 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants