-
Notifications
You must be signed in to change notification settings - Fork 46.9k
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
Bug(regression): PropTypes.resetWarningCache has no effect in react@next #18251
Comments
importing the cache would defeat the purpose of inlining, which is to have fewer dependencies. Tricky. |
I'm still not really clear on the value of having fewer dependencies, especially in the case of prop-types, which facebook controls. |
This is a bit unfortunate. But to be honest, we didn't really sign up to respect this setting in React itself. The fact that the
While I probably won't convince you,
The purpose was to get rid of imports.
Prop-types is a legacy feature. It's not something that is super important to React going forward. We try to keep it working, but it's not a first-class "React API". There is no need for us to keep the implementation separate when the contract is so simple and we could just call into the user code from React here. On the other hand, changes related to ESM and just our bundling process is always more complicated when there's dependencies involved. We have so few dependencies that this isn't worth the complexity. It is easier to get rid of them. |
This will break many test suites. Could React expose a way to reset the warning cache? |
If you require One can always call
This is actually interesting because it exposes another problem with this approach. Even if a library "resets" the propTypes cache, that doesn't help for any other React warnings. So it doesn't actually solve the problem for libraries that want to verify that React warnings aren't firing for it. You still need a better solution. Again, Maybe there could be some centralized cache for deduplication that would work for all warnings. And React could pass it to |
The work point of moving prop-types to a separate package was so React didn’t have to expose it. Will React be exposing it now? The test suites I’m concerned about don’t care about non-propType react warnings. |
Separately, whether it works by accident or not isn’t really relevant; if it works and you break it, you’re breaking people - in a non-major. Regardless of technicality debates wrt semver, that seems like a pretty user-hostile position to take for some kind of vague maintainability benefit for the react team. |
I would also point you to https://www.w3.org/TR/html-design-principles/#priority-of-constituencies, something that’s generally considered a good principle in all software design - namely, that users always matter more than authors. |
React won't be exposing the
We have a versioning policy here which notes that we don't consider changes to DEV-only behavior like warnings to be breaking. In general case, this is because warnings are how we prepare people for other major changes. I agree this isn't exactly the case that section is meant to cover in spirit, but I hope it explains why we consider this change acceptable. If test suites are written specifically to check React's console output, they will break because we add new warnings, reword warnings to be clearer, sometimes remove them, change deduplication heuristics, fix bugs, and so on. If every behavior change to warnings was considered breaking, we'd be incrementing majors every week, and I doubt the ecosystem would be better for it. My suggestion is to either not write tests that assert on console output, or be prepared that changes to these tests will not follow the same schedule as changes to production behavior. We've reiterated this multiple times so this isn't really a new stance. It's part of how we release React. |
There's a critical difference here - non-propType warnings are about misusing React, and I think it's reasonable to consider this non breaking. propType warnings, however, are about misusing a component, and this does not seem to me to be in the same category. |
Just to give a bit more background how we're using this: We're not checking react's console output (or at least we don't mind rewriting tests if those change). However, The ability to test these validators is now severly limited because watchmode doesn't work for them. This means working on them takes much more work (since I have to restart the test every time) which means I'm less like to work on them to improve DX. The dilemma here is that I don't think propTypes is the right choice for these. I would've preferred React.warn and React.error but these were also stripped What makes this stance come across so user-hostile is that this wasn't done to enable something else (fix a bug, add a feature, improve perf). It was only done because you could and is then dismissed with "just use jest". Apart from the cost of having to migrate to another test runer, jest is also lacking a critical feature over other runners: it can't run in the browser. Would a |
Let’s step back for a second. Can you explain in more detail why explicitly calling |
|
I wasn't aware of that method. But apparently it only fires once:
-- https://github.com/facebook/prop-types#proptypesresetwarningcache This would break our tests in watchmode. We never had a use for resetting modules between tests since the modules under test were stateless (at least the parts we wanted to test). It's also not trivial to do in mocha (requires 3rd party package).
It does not include the component stack on the server nor can we deduplicate the warning by component stack. |
Previously we were appending a random string to the message for cache busting but that hurt readability. We'll probably go back to that approach and hide it in a custom matcher. I'm just a bit worried that checkPropTypes will also go away in a minor with the same justification. |
Before you assume malice, please help me understand the issue better.
Yes, so you need to call The only change is that If you call Can you please explain why this doesn't work for you?
I'm sorry that you got the impression that we don't care about our users and are going to remove APIs in minors. I don't believe this is what happened here. We didn't remove any API in a minor, and don't intend to.
The only thing we "removed" is the ability for Given that the alternative ( |
@gaearon because the best way to test propTypes isn't to unit-test an individual custom propType, it's to attempt to render a component, and fail your tests when React issues propType warnings. that, specifically, is the primary benefit of |
If that is indeed the case then it would work for me. I simply assumed that resetWarningCache works the same for .propTypes and checkPropTypes. Let me try checkPropTypes and then I'll update the documentation since I don't think it's obvious. In a perfect world I wouldn't unit test propTypes with resetWarningCache but that isn't that important to me. I'm more interested in a practical compromise than some perfect theoretical approach. |
It technically works for us but we have to mock a couple of internals: PropTypes.checkPropTypes(
ButtonBase.Wrapped.propTypes,
{ classes: {}, component: Component },
'prop',
'ForwardRef(ButtonBase)',
);
So this works for us but there are quite a bit of internals we have to mock. Could you explain why it wouldn't work for you to expose |
It is a new API. We don’t add new APIs lightly. For the ones we do, we want them to stick around for a long term. I don’t know if even calling PropTypes at all is something we want to support in longer term. They are a relatively poor replacement for type checking and have nothing to do with UI. We understand many people care about them, but it’s pretty arbitrary that you would limit runtime type checking to UI alone. Why not all modules? The point of extracting them was in part to make that easier and more natural. So I imagine in distant future React may stop calling them and instead there would be a codemod that turns your components into: function Button(props) {
checkPropTypes(props, Button.propTypes)
// your code
} Effectively fully moving them into userland. With a vision like this, it doesn’t make sense to add more propTypes-specific APIs to React itself. |
Can you link me to components and tests in question? I’m low key wondering why you want to test prop types at all. They’re already fully declarative so it seems like writing the same code twice. Unlike components, they (usually) don’t contain any logic so the only way to mess them up is to have typos. Which would be caught by a shallow test asserting their presence with given names. As long as your other tests (for UI) don’t trigger warnings, I don’t know what it is that you want to be testing. I understand the need to test a custom propType validator but that can be done in isolation easily. |
I think my overall conclusion is that I see some value in being able to reset all warnings, but I struggle to see value in “testing propTypes” because they don’t contain any custom logic. The only kind of test I can imagine being valuable is making sure legit use of your component doesn’t trigger them. But you already get that even if you don’t reset warnings. I agree non-determinism is best avoided in tests, but that logic applies much more importantly to other React warnings that point out real bugs. So if you care about this you either need |
So like a Anyway this is at least resolved for me personally since we can leverage checkPropTypes.
I'll ping you in the PR where we migrate from .propTypes to checkPropTypes since I want to go over these custom propTypes myself just in case they are actually not necessary. |
Deleting the require cache doesn't work in node, unless you delete all of the cached code of your entire graph - because modules cache things at module level.
Separately, propTypes are better than types for most cases - you can propType an integer, or strings that match a regex, for example, none of which you can do in TS. propTypes and types are complementary, and it's simply false to claim that propTypes are a poor replacement for type checking. |
React compiles to bundles. So deleting
Sure. In my experience of looking at tens of thousands of components both in open source and at FB, this powerful capability is rarely used in practice. For the cases where runtime validation specifically is important, manually calling What I'm saying isn't that PropTypes are useless. It's more that most of their use cases have been superseded, and the remaining use cases aren't tied to React so a general solution would make sense. |
|
@gaearon since every component in every app everywhere does |
Ah right. I forgot this happens in the React bundle rather than ReactDOM. (Where the majority of warnings lives.) |
React version: 0.0.0-235a6c4af
Steps To Reproduce
PropTypes.resetWarningCache()
Link to code example:
Behavior on
0.0.0-235a6c4af
Behavior on
16.13.0
The current behavior
Warnings are logged once
The expected behavior
Warnings are logged twice. This was the behavior in 16.13.0
Context
Useful for testing custom propTypes warnings. When a test is watched and modules can't be reset between runs
resetWarningCache
was useful. Otherwise the test behavior would change between test runs.Pretty sure this is caused by inlining
prop-types
in #18127. I think we can keep inlining the code and only import the cache so that it is shared with the regularprop-types
package andPropTypes.resetWarningCache()
keeps working.The text was updated successfully, but these errors were encountered: