-
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
Add fail-fast mode to React #1753
Comments
👍 from me at least, I understand wanting identical behavior in DEV and PROD, but to me it seems it would only be a problem if it was the other way around (error in PROD and warning in DEV). Too many times have I found myself troubleshooting an issue already printed in the console. Although there's a problem with it being an option too, third-party modules are not guaranteed (or even likely) to strictly follow your current definition of what is mandatory. So unless it's per file/module somehow, it would be problematic. |
I think it's likely that we'll do this, possibly as the default behavior. |
nice @spicyj Also I thought React used In fail-fast / strict mode / dev it would be nice to freeze props (deeply) and state so that we can be sure no component is actually updated in place. The drawback is that to really enable fail-fast with this, this requires the user to add |
@slorber While it's arguable that it is bad practice to change state in-place, React does not enforce immutability, it only (strongly) encourages it. |
I'm a huge fan of this idea. It is definitely what I want to enforce in my project. I have tried manually freezing my props objects, but there are various React internals that can end up cloning the object and thereby nullifying the freeze. It would be very nice to be able to simply opt-in to frozen props. |
@davidtheclark I'm using freeze myself and did not have any problem. Note that freezing is not recursive, so if you freeze I use this: |
I didn't realize freeze wasn't recursive, thanks for pointing that out. |
Thanks @slorber. Deep freezing isn't the issue I'm having, but React internals cloning the object I'm passing in. When are you freezing the object? Within the component, or before it is passed to the component (as spread or through a factory)? The situation I'm referring to is that when I pass in a frozen object to become props -- through spread in JSX or an element factory -- it is exposed to the component unfrozen. I see two places that probably cause this: In So if I have recursively frozen my passed-in-props-object, what comes out and is available in the component's methods, the component-props-object, Then essentially the same thing happens when passing JSX spread attributes because the spread implementation creates a new object that is assigned the properties of the object you pass in: https://github.com/facebook/react/blob/master/src/browser/ui/React.js#L82 The way I'm patching this now is a simple mixin, re-freezing props within the component, after they've gone through var FreezePropsMixin = {
componentWillMount: function() {
Object.freeze(this.props); // or deepFreeze()
},
componentWillUpdate: function(newProps) {
Object.freeze(newProps); // or deepFreeze()
}
}; (As mentioned above -- I don't have to deep freeze the object again if I deep froze it already, because those properties that were deeply frozen are still the same references.) Sorry this is so long. I can of course keep using my
|
@davidtheclark So to make it short what I understand of your point is that freezing an object and injecting it as props does throw an error when you try to modify the object itself inside the component, but it does not prevent from modifying the object reference in the props object as the props is always a new unfrozen object I mean you can't do Yes it would be nice if React let use automatically froze the properties. Maybe you can build your own component factory, like I do in my framework Atom-React (http://stackoverflow.com/questions/25791034/om-but-in-javascript), to automatically include some mixins everywhere: |
I'm probably missing the point. Why freeze I doubt the first use case is worth protecting against because it's really hard to write something like this by accident. The second use case, maybe more so. What do you think? Am I missing something? |
I'll try to be more concise and clear. @slorber I think we're on the same page. If @gaearon Here are some reasons I'd want to freeze Both of the possibilities you raise for mutating I can think of three ways to pass props: 1. regular JSX attributes passed one at a time, 2. full object passed as JSX spread attributes, 3. full object passed to a factory. 2 and 3 could be addressed if React were to check whether the object you passed in is frozen, and if so freeze (I think none of those changes are too significant --- if the React-strict-mode were opt-in it wouldn't force anybody not being strict already to change the way they use React.) |
After my #2540, React will warn you automatically if you mutate this.props. |
Very nice. |
Just want to voice more support for this behavior. It was surprising to me to find that the isRequired prop validator in particular just throws a console warning. It makes it difficult to test, for one thing. |
@cappslock if I remember my tests correctly the 0.14 version will be better regarding props validation. Not sure but I think it throw errors, or at least log error instead of warning |
Hey, This is an old thread but as we recently moved react warnings from console.warn to console.error, I was wondering if it was possible to trigger a callback everytime React detects a problem. I understand you may not want to throw on bad proptypes as it could lead to different app behaviors in dev/prod mode, but it would be really nice if we had the hability to plug our own code when something bad happens. Let me explain: sometimes the developers do not watch the console and do not notice react errors are logged. If I could plug a Is this possible? |
@slorber in the meantime we are using a little hack in our unit test setup to fail tests when they cause warnings:
|
@c089 I've used something similar in the past but I don't like to proxy console.error as if we do this it messes up with the stacktrace that is shown in chome console. |
I like the proposals in this thread. Is there a way to freeze all the props in some way, in the meantime? |
I’m interested in adding this to Create React App in the meantime: facebook/create-react-app#783. |
I think it’s pretty unlikely we’ll crash your app on a failing prop, but you can do this yourself by overriding That said we do “fail fast” on crashes now with the new error handling behavior in React 16. Instead of keeping the tree around in a broken state, we unmount it, but let you opt into graceful handling with error boundaries. So, in a way, I think we did add fail-fast mode to React. (And you can achieve the same for warnings by overriding |
I am doing this right now, and it seems to work pretty sweet: describe("...", () => {
beforeAll(() => {
jest.spyOn(console, "error").mockImplementation(error => {
throw error;
});
});
afterAll(() => {
console.error.mockRestore();
});
// ...
}); It will, only for testing, convert every |
When using components with missing/invalid prop, then a warning is logged.
Same when a child key was not provided.
I would like an error to be thrown instead.
This has already been discussed on some issues like: #1587
By the way, I totally support this related issue, to ensure proper Proptype documentation of all components, but would require an error instead of a warning :)
The more we fail in dev, the better. It would be nice to be able to use React in a very strict way, by using some configuration attribute or something...
One other thing I would probably add is to enforce all components have a name.
See #1751
The text was updated successfully, but these errors were encountered: