I have a huge number of console errors like this appearing in my app:
Warning: React does not recognize the textStyle prop on a DOM element. If you intentionally want it to appear in the DOM as a custom attribute, spell it as lowercase textstyle instead. If you accidentally passed it from a parent component, remove it from the DOM element.
Ideally I would fix the errors but sadly that's not possible as I'm using Styled System with Styled Components:
https://github.com/styled-system/styled-system/issues/1044
As a less than ideal workaround Id like to disable certain errors from the console for the development version of React. Can this be done?
Not sure if it matters but I'm using React Native Web.
You can override the console.warn method with your own function that filters out the warnings you want to ignore:
const consoleWarn = console.warn;
const SUPPRESSED_WARNINGS = ['arning text - I will n'];
console.warn = function filterWarnings(msg, ...args) {
if (!SUPPRESSED_WARNINGS.some((entry) => msg.includes(entry))) {
consoleWarn(msg, ...args);
}
};
console.warn('I\'ll appear as a warning');
console.warn('warning text - I will not');
I'm not sure which console method react is using internally, so you may need to do the same for console.info, console.log and console.error.
You can also just use the production version of react, which suppresses all warnings by default, but of course you can't pick and choose, you loose all warnings in that case.
Related
I have been working in a react typescript project for awhile and the way that we had been type-checking props was with the React.FC generic. Going into the react typescript documentation I find code like the following:
interface DateProps {
iso8601Date: string;
message: string;
}
const DateComponent: FauxactFunctionComponent<DateProps> = props => (
<time dateTime={props.iso8601Date}>{props.message}</time>
);
However I just started a new project and there have been a few updates and we updated the eslint to the recommended for react. The new eslint rules are throwing the error:
"missing in props validation eslintreact/prop-types"
This can easily be avoided by following changing some linting rules recommended here:
"rules": {
"react/prop-types": "off"
}
I am tempted to turn off this linting rule and do it as we have done in the past. I don't think I see any added benefit from the docs. But am asking if there is something I am missing with the use of prop-types and why might it be better than the original method? I am leaning towards turning it off.
React PropTypes is a runtime check: in case of incorrect types / missing/extra props, you would get a runtime error in the browser console pointing out the discrepancy (besides possibly a crashing component in case of missing prop...).
It is useful when there is no static type check in the project, as described in the documentation:
For some applications, you can use JavaScript extensions like Flow or TypeScript to typecheck your whole application. But even if you don’t use those, React has some built-in typechecking abilities.
In your case, you use TypeScript for static type check of the props, it is very good at this job in almost every situation (minus very acute corner cases).
Besides, the main IDE's (in particular VS Code) have TSX support that leverage your prop type definition to validate them within the JSX syntax, as if it were a normal function call.
PropTypes also enables specifying default prop values; it is the main way to do so in class-based components. But with Function components, we can simply use JS default parameters (even when destructuring).
Therefore, in line with the docs, if you properly specify the TS types on your props, and use only Function components, there is need to double the work with React PropTypes, and you can safely disable this linter rule.
Would anyone know how to debug and fix (or mute) following warning (apparently, Mantine is dropping react-popper in next major release)?
Everything works fine, but warning is making it very hard to debug other issues.
Warning: flushSync was called from inside a lifecycle method. React cannot flush when React is already rendering. Consider moving this call to a scheduler task or micro task.
at Popper (webpack-internal:///./node_modules/#mantine/core/esm/components/Popper/Popper.js:67:3)
at div
at eval (webpack-internal:///./node_modules/#mantine/core/esm/components/Box/Box.js:42:18)
at Popover (webpack-internal:///./node_modules/#mantine/core/esm/components/Popover/Popover.js:76:85)
at O (webpack-internal:///./node_modules/styled-components/dist/styled-components.browser.esm.js:30:19811)
at SecretTextareaWithLength (webpack-internal:///./src/main/routes/Create.tsx:106:48)
at form
at div
at O (webpack-internal:///./node_modules/styled-components/dist/styled-components.browser.esm.js:30:19811)
at Create (webpack-internal:///./src/main/routes/Create.tsx:291:48)
at Routes (webpack-internal:///./node_modules/react-router/index.js:920:5)
at MenuEvents (webpack-internal:///./src/main/MenuEvents.tsx:34:55)
at Router (webpack-internal:///./node_modules/react-router/index.js:854:15)
at MemoryRouter (webpack-internal:///./node_modules/react-router/index.js:767:5)
at MantineProvider (webpack-internal:///./node_modules/#mantine/styles/esm/theme/MantineProvider.js:66:3)
at App (webpack-internal:///./src/main/App.tsx:40:35)
this is a bug in mantine When using Popper. it will be fixed in the next release.
one thing you can do is hack your local react copy to add conditional logic and skip this warning.
another simple way is overwriting the console methods :
console.warn = () => {};
console.warn('warnings skipped.');
but in this case all warnings will be ignored
Solved
Issue is tracked on github
I was attempting to test custom hooks using the react testing library, and the hook I was trying to put under test requires multiple context providers to work correctly. (authentication and notification)
The documentation here only outlines creating a wrapper with a single provider like so:
const wrapper = ({ children }) => <ContextProvider>{children}</ContextProvider>
However, my implementation needed something more complex, like so:
const wrapper = ({ children }) => (
<ToastProvider>
<NotificationProvider>
<AuthProvider>{children}</AuthProvider>
</NotificationProvider>
</ToastProvider>
);
This was was failing at every attempt with the errors:
TypeError: parentInstance.children.indexOf is not a function
OR
Invariant Violation: Drop(...): Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null.
Leading me to believe there was no clear way to provide the right context without abandoning renderHook all together and building a test component that could fire off the necessary behaviors manually.
After a lot more digging I found this error buried in the logs:
Warning: An invalid container has been provided. This may indicate that another renderer is being used in addition to the test renderer. (For example, ReactDOM.createPortal inside of a ReactTestRenderer tree.) This is not supported.
Surely enough, it turns out there is a conflict with react-test-renderer and react-dom which causes calls to ReactDOM.createPortal to fail when under test. I assume this is somewhere in the ToastProvider, but the workaround is pretty simple.
Solved by adding this to the top of my test:
ReactDOM.createPortal = node => node
I am creating a calendar date selection function component for assigning days to schedules in my React app and I wanted to be able to pre-populate calendar with the existing data so that it could be modified by the user.
This is what I have so far:
const initialOptions: { [key: string]: number[] } = {};
for (const option of Object.keys(props.options)) {
const dates = props.options[option].dates;
initialOptions[option] = dates ? dates : [];
}
const [selectedDates, setSelectedDates] = useState(initialOptions);
However, when I try and render the page, I get this:
React Hook "useState" is called conditionally. React Hooks must be called in the exact same order in every component render. Did you accidentally call a React Hook after an early return? react-hooks/rules-of-hooks
After reading through the react rules of hooks, I didn't see anything that indicated that react was depending on the value of the parameter to "associate local state with [my useState() call]". All it really said was...
As long as the order of the Hook calls is the same between renders, React can associate some local state with each of them.
So why is react complaining at me when I am calling useState() in top-level react code that is outside of any conditional statements or functions as per their own rules?
The comments on this question that basically said calls to react hooks need to be before any control structures, even if they are unrelated were what pointed me in the right direction.
The answer provided in the comments was not quite satisfactory though since I needed to process the inital value of selectedDates if an initial value was provided and have that available before I called useState() in order to pass it as a parameter.
Despite being perplexed by this and the somewhat nonsensical nature of this solution (order shouldn't matter with two barely-related pieces of code, right?), I managed to refactor my logic such that it both stopped react from complaining AND allowed me to still conditionally set the selectedDates in my react calendar component.
Here's what I ended up with:
const initialOptions: { [key: string]: number[] } = {};
Object.entries(props.options).forEach(value => {
const [id, options] = value;
if (options.dates) {
initialOptions[id] = options.dates;
}
});
const [selectedDates, setSelectedDates] = useState(initialOptions);
As someone who isn't that familiar with the internals of react, it seems that either:
the react team got something wrong when writing the ESLint plugin for the react hook rules, or
there was a functional limitation in how ESLint works that doesn't allow for a more specific/accurate check, causing the developers to go with a "better safe than sorry" approach by using a less specific check that still caught rule violations as well as edge cases like this one
So overall, my conclusion is, by replacing my for loop with a call to .forEach(), the ESLint
plugin saw my loop as a function rather than a control structure/conditional and allowed my code to pass the test and run without issue.
Now, as a self-described "junior" react developer, i'm pretty sure that tricking ESLint into not giving an error like this is not a good long-term solution. Ideally ESLint rules probably need updating to better check for improper use of conditionals, and/or the react docs should be updated with an example for how to conditionally set a hook's default value in a way that doesn't violate the rules of react hooks.
EDIT: I have created an issue for the react documentation in order to find out what a good long-term solution to this would be and get the documentation and/or ESLint plugins updated if necessary
If you ignore the warning that means that you are setting your expectations wrong on how your Component's code will be executed during renderings.
Just by looking at initialOptions, you can see that the initial value is based on incoming props. In React when the props change your Component gets re-rendered, the initialOptions is re-evaluated BUT it's NOT updated again by useState(initialOptions).
Sure you can say: "but my useState(initialOptions) is not wrapped around any condition!". While that is absolutely true, you didn't inform React that selectedDates needs to be updated between renders. It's value is still the first initial value when the Component was rendered first time.
You need to move the foreach logic into a useEffect with dependency to props.options.
Example based on your code:
const initialOptions: { [key: string]: number[] } = {};
const [selectedDates, setSelectedDates] = useState(initialOptions);
useEffect(() => {
// Here it's okay to have an optional condition!
if (!props.options.length) { return false; }
const newOptions = [];
Object.entries(props.options).forEach(value => {
const [id, options] = value;
if (options.dates) {
newOptions[id] = options.dates;
}
});
setSelectedDates(newOptions);
}, [props.options]);
I've prepared a sandbox example which demonstrates why the rule "Only Call Hooks at the Top Level - Don’t call Hooks inside loops, conditions, or nested functions." must be respected https://codesandbox.io/s/immutable-meadow-xvy50t?file=/src/Component.js <-- click the body of the page repeatedly and notice that the component doesn't update.
I'm currently working on a medium sized reactJS application and get the following error message after I click a button on a component:
Warning: setState(...): Can only update a mounted or mounting component. This usually means you called setState() on an unmounted component. This is a no-op.
How can I debug this more easily? Why doesn't reactJS give me a specific component name where this rule was violated?
How would you do it?
You can override console.warn to make it throw instead of log when the provided message matches a certain pattern. In your case, you'd do:
var warn = console.warn;
console.warn = function(warning) {
if (/(setState)/.test(warning)) {
throw new Error(warning);
}
warn.apply(console, arguments);
};
The stack trace of the error will then point to the line causing the warnings.
Actually, the best way to solve this issue is by changing some react code locally.
This pull-request specifically points out how to modify src/renderers/shared/reconciler/ReactUpdateQueue.js to get the component that illegaly sets state.
As this pull-request was already merged into the repo, it shouldn't be to long before it will be integrated into an npm version of react, one could hope.