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

Feat : emulate string outside text error #1070

Conversation

pierrezimmermannbam
Copy link
Collaborator

Summary

Throw errors when strings are rendered outside Text to simulate native behaviour (#1032 )

On initial render we make a first check and then using a React.Profiler we perform a new check on each update by using the screen object to access the instance. The check at mount is done directly in the render method because the screen object is not updated yet with the render result. In the onRender prop of the React.Profile we verify that the phase is update before performing a check so it doesn't run on mount.
I also had to refactor a bit the render function so that this behavior would only affect the rendering of components and not of hooks because in the case of hooks the instance is not defined in the screen object, which resulted in errors on update.

Test plan

I added a test case for rendering, rerendering and updating with fireEvent and checked each time that it threw the expected error

@pierrezimmermannbam pierrezimmermannbam force-pushed the feat/emulateStringOutsideTextError branch from d6b00e1 to 2b2d44f Compare August 20, 2022 15:44
Copy link
Member

@mdjastrzebski mdjastrzebski left a comment

Choose a reason for hiding this comment

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

Added some initial comments.

Copy link
Member

@mdjastrzebski mdjastrzebski left a comment

Choose a reason for hiding this comment

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

I've added a request for some addtional test, I have a hunch that we won't be able to simulate that perfectly until we solve #967 .

@mdjastrzebski
Copy link
Member

The PR seems to be almost ready. We still need to pick meaningful render option name for it. I would suggest to prefix it with experimentalXxx, where xxx is whatever name we will choose. That way we could release it to the users, inform them that it's kinda new so might still be some unexpected errors, and also give us ability to fix them without releasing major version, as typically in OSS experimental features breaking changes are not considered breaking change for the whole dependency. @pierrezimmermannbam @AugustinLF @thymikee Wdyt?

@pierrezimmermannbam
Copy link
Collaborator Author

I changed the implementation to use toJSON, the validation should work fine for every case now, what remains to be done is deciding the name for the option and customizing the error message so that it's clearer. I don't know about logging a part of the tree but I'd say adding the string that is being rendered outside a Text component would be a good start. As for the name of the option, experimentalValidateStringsRenderedInText as suggested by @mdjastrzebski looks good to me

@pierrezimmermannbam
Copy link
Collaborator Author

pierrezimmermannbam commented Aug 30, 2022

Also there is a small issue when running tests, the React.Profiler logs errors so there are outputs of errors from the tests. This could be fixed by overriding console.error in the tests that trigger errors so that it doesn't do anything. It's not ideal though, maybe there is a better way to do this ?

Capture d’écran 2022-08-30 à 19 17 36

@AugustinLF
Copy link
Collaborator

Also there is a small issue when running tests, the React.Profiler logs errors so there are outputs of errors from the tests. This could be fixed by overriding console.error in the tests that trigger errors so that it doesn't do anything. It's not ideal though, maybe there is a better way to do this ?

I'd say it's fair in this case to override console.error and add an explicit filter for the error containing <Profiler> component or something like that

@pierrezimmermannbam
Copy link
Collaborator Author

Also there is a small issue when running tests, the React.Profiler logs errors so there are outputs of errors from the tests. This could be fixed by overriding console.error in the tests that trigger errors so that it doesn't do anything. It's not ideal though, maybe there is a better way to do this ?

I'd say it's fair in this case to override console.error and add an explicit filter for the error containing <Profiler> component or something like that

I have overriden console.error in the tests that logged errors so that it doesn't log errors from the Profiler

@pierrezimmermannbam pierrezimmermannbam requested review from mdjastrzebski and AugustinLF and removed request for mdjastrzebski and AugustinLF August 31, 2022 20:48
Copy link
Member

@mdjastrzebski mdjastrzebski left a comment

Choose a reason for hiding this comment

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

Awesome work @pierrezimmermannbam ! Seems like your nearing to the end. I really like you were able to use JSON tree to run the assertion code.

On major thing that brings my attention is the complexity around render/renderComponent function. I have suggest an approach that would allow us to use the original render while having a separeterenderWithValidateStrings, instead of current more complex flow.

@pierrezimmermannbam pierrezimmermannbam force-pushed the feat/emulateStringOutsideTextError branch from 9b8412f to aeca6d6 Compare September 3, 2022 18:49
Copy link
Collaborator

@AugustinLF AugustinLF left a comment

Choose a reason for hiding this comment

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

Stellar work! Really looking forward using that.

Comment on lines 363 to 365
test(`it should throw
- when one of the children is a text
- and the parent is not a Text component`, () => {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
test(`it should throw
- when one of the children is a text
- and the parent is not a Text component`, () => {
test(`it should throw when one of the children is a text and the parent is not a Text component`, () => {

});

test(`it should throw
- when a string is rendered within a fragment rendered outside a Text`, () => {
Copy link
Member

Choose a reason for hiding this comment

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

```suggestion when a string is rendered within a fragment rendered outside a Text`, () => {

@mdjastrzebski
Copy link
Member

I've extracted the tests into separate render-stringValidation.test.tsx file, as the original render.test.tsx got pretty long. I've also replaced error snapshots/inline snapshots with cleaner toThrow checks.

@mdjastrzebski
Copy link
Member

Awesome work @pierrezimmermannbam! Merging it 🚀

@mdjastrzebski mdjastrzebski merged commit f80745f into callstack:main Sep 19, 2022
@pierrezimmermannbam pierrezimmermannbam deleted the feat/emulateStringOutsideTextError branch September 19, 2022 13:52
@mdjastrzebski
Copy link
Member

🎉 This PR is included in version 11.2.0 🎉

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.

3 participants