I've got a very simple hook that looks like this:
export const QuickViewCell = props => {
const [hover, setHover] = useState(false)
const handleMouseEvent = () => {
console.log('calling')
setHover(!hover)
}
console.log('hoverState', hover)
return (
<Box onMouseEnter={handleMouseEvent} onMouseLeave={handleMouseEvent}>
<Text size="small">
{String(props.data.name)} this is my custom cell and it is amazing
</Text>
</Box>
)
It works when placed in one part of the project, but doesn't when placed in another. Meaning, the handleMouseEvent function is always being called, but the component isn't re-rendering with the new state. React and React-Dom are at 16.8.1. I'm not getting any errors. I'm not sure where to look for the bug.
If I change it to a class component using setState, it works fine, which makes me think I've got an incompatibility issue somewhere, but without an error message, not sure where to look. Or I'm missing something more obvious :)
Anyone experience something like this? Is there a way to determine if there is an incompatibility with another package?
Based on the following wording in your question:
It works when placed in one part of the project, but doesn't when
placed in another.
I assumed that the two places were part of the same build (i.e. same package.json). If that was the case, it seemed unlikely that it was an incompatibility issue. But the following recent comment:
The code for this component is identical in both cases, it's mainly
the packages that are different.
makes it sound like the two cases are part of separate builds. If this is true, then I think the hook-incompatibility theory is reasonable, though I'm not entirely convinced because I would expect a message in the console in that case (but I suspect there are some variations on the multiple-react-copies issue that wouldn't cause a message in the console).
The following page from the documentation has instructions on troubleshooting this:
https://reactjs.org/warnings/invalid-hook-call-warning.html#duplicate-react
On that page you'll find the below instructions for determining whether you have multiple versions of react in play.
You can run npm ls react-dom or npm ls react-native in your
application folder to check which version you’re using. If you find
more than one of them, this might also create problems (more on that
below).
And then further down:
If you use Node for package management, you can run this check in your
project folder:
npm ls react
If this doesn't show any surprises (i.e. just shows one copy of 16.8.1 for both react and react-dom), then I would move forward with assuming there is something other than an incompatibility going on and would want to see the code that uses QuickViewCell in the problem case.
On a tangential note regarding jayarjo's recommendation to use the "functional update" syntax, I think the more appropriate way to update this hover state in order to more easily know that it is correct/robust would be to explicitly pass the boolean rather than doing a toggle of whatever the state currently is.
For example:
export const QuickViewCell = props => {
const [hover, setHover] = useState(false)
return (
<Box onMouseEnter={()=>setHover(true)} onMouseLeave={()=>setHover(false)}>
<Text size="small">
{String(props.data.name)} this is my custom cell and it is amazing
</Text>
</Box>
);
}
This makes it easier to be confident that you won't accidentally get in a state where hover is stuck as the opposite of what it should be.
When previous state is used to calculated next one, it is recommended to use functional updates.
So instead of setHover(!hover) try setHover(hover => !hover). That should do.
Related
I heard that strict mode helps to write React code in best practices way by throwing warnings for life cycle methods removal. I read about it from this article on Medium.
Is my understanding correct? How effective is strict mode? Is it only for unsafe life cycle methods? If not can I use this feature in functional components?
import { StrictMode } from "react";
class Test extends Component{
render(
<StrictMode>
//Some other child component which has all lifecycle methods implemented in it
</StrictMode>
);
}
React's StrictMode is sort of a helper component that will help you write better React components, you can wrap a set of components with <StrictMode /> and it'll basically:
Verify that the components inside are following some of the recommended practices and warn you if not in the console.
Verify the deprecated methods are not being used, and if they're used strict mode will warn you in the console.
Help you prevent some side effects by identifying potential risks.
As the documentation says, strict mode is development oriented so you don't need to worry about it impacting on your production build.
I've found it especially useful to implement strict mode when I'm working on new code bases and I want to see what kind of code/components I'm facing. Also if you're on bug hunting mode, sometimes it's a good idea to wrap with <StrictMode /> the components/blocks of code you think might be the source of the problem.
So yeah, you're in the correct path to understanding strict mode, keep it up, I think it's one of those things you understand better when you play with them, so go ahead and have some fun.
Warning: StrictMode will render the components twice only on the development
mode not production.
For instance, if you're using getDerivedStateFromProps method like so:
static getDerivedStateFromProps(nextProps, prevState){// it will call twice
if(prevState.name !== nextProps.name){
console.log(`PrevState: ${prevState.name} + nextProps: ${nextProps.name}`)
return { name: nextProps.name }
}
return {}
}
The getDerivedStateFromProps method will call twice.
Just to let you know this is not a problem, it's just because you're wrapping your main component with <StrictMode> in the index.js file.
StrictMode renders components twice in order to detect any problems with your code and warn you about them.
In short, StrictMode helps to identify unsafe, legacy, or deprecated APIs/lifecycles. It's used for highlighting possible problems. Since it's a developer tool, it runs only in development mode. It renders every component inside the web app twice in order to identify and detect any problems in the app and show warning messages.
StrictMode is a tool for highlighting potential problems in an application. Like Fragment, StrictMode does not render any visible UI. It activates additional checks and warnings for its descendants.
I am a very, very amateur programmer but I've been trying to get into JavaScript and ReactJS recently. It's not pretty and I don't know what most of the stuff does, but I figured I would follow a YouTube tutorial on some things that I was interested in, so I found one that I liked and followed it. However, at 8:52, React threw up an Invalid Hook Call error. My problem is, even though I'm pretty sure the documentation has a solution, my amateur level doesn't allow for me to read it and understand it. Basically: I have no idea what the docs say. Below is an attached screenshot of the error (there's more, if anyone requests for me to scroll down) and the link to the completed code. If anyone could help, that would be amazing, but based on the number of comments and the lack of people acknowledging this error I would assume it's decently hard to reproduce. Also, if it's any help, I had to directly link to a few things (such as React-Bootstrap) because react wouldn't recognize just the plain words. Thank you in advance :)
Screenshot
GitHub Code
This is almost always a problem with #2 in your screenshot ("You might be breaking the rules of Hooks"). The most common error (though I didn't see this in your video) is calling hooks inside a child function of a function component, i.e.
const Component = () => {
// Good - hook is called at root of function component
const selectorData = useSelector(getDataSelector);
// Bad - hook is called inside a child function and has no context for hooks
useEffect(() => {
const data = useSelector(getDataSelector);
}, []);
return (
// ...
);
};
The test in the code below is a very common pattern I have seen both online and at a company I interned at:
import React from 'react';
import { shallow } from 'enzyme';
import Button from './Button';
describe('Test Button component', () => {
it('Test click event', () => {
const mockCallBack = jest.fn();
const button = shallow((<Button onClick={mockCallBack}>Ok!</Button>));
button.find('button').simulate('click');
expect(mockCallBack.mock.calls.length).toEqual(1);
});
});
What I don't understand is why bother writing this test? If a component has an onClick property, and onClick is supplied a callback, of course clicking that component will result in the callback being called. When would this ever fail? What am I not considering here?
Actually this test testing two things:
Button calls provided onClick handler, if your teammate perform some refactoring in Button component and forgot to provide onClick function to native button element this test will fail. This kind of problem will be discovered in PR when someone review changes or in testing but none of this two guarantees you that broken button wont appear in production.
Button renders, i.e. some library that you use to style that Button is broken, it is common case in javascript world. then/is-promise 1-liner library with 11+ million usages has been broken today. So if you test code it will fall locally or on CI before you merge it.
But with shallow rendering second case wont work as expected here because it doesn't render all components in the react tree with running all lifecycle hooks, it is considered as bad practice in testing, you can checkout post by Kent C Dodds Why I never use shallow rendering for more details.
It is important part of testing culture to test everything, the code is not working until you test it, if your code is simple, the test will be simple too. It is good code. If your code is entangled and complicated most likely you won't be able to write a test for your code at all. You will have to refactor it to make it testable and simple. It is praiseworthy that you are thinking about the meaning of the test, sometimes tests can be useless but your example is not.
I have an existing application in which I've encountered a problem.
The root of the problem, as far as I know, lies in a broken Apollo query (for example, when trying to spread data whilest it's still undefined). This leads to a wierd UI, in which there are humongous icons and to a warning of such kind:
Warning: Prop className did not match. Server: "MuiSvgIcon-root-69" Client: "MuiSvgIcon-root"
After some research, I found out that the reason of this may be the disableGeneration prop which should be set to true for performance reasons, but I also suspect that if it's turned on then MUI skips the className generation and yields correct classnames as the result.
The question is: what is the correct way to use it, or is there any other way to fix this issue? My stacks is as follows:
next.js 9.1.1
material UI 4.6.0
react-apollo 3.1.2
I have tried several combinations of using StylesProvider and ServerStyleSheets, though I haven't managed to get the job done. Currently I'm using this in _document.js:
const sheets = new ServerStyleSheets({
injectFirst: true
});
And this is the way I use getDataFromTree, though it looks quite odd to me:
const sheets = new ServerStyleSheets({
disableGeneration: true
});
await getDataFromTree(sheets.collect(<AppTree {...appProps} />));
I had done a lot of googling but couldn't find a concise result of how to use SSR with Apollo & Material. Any help would be much appreciated :)
I have a React project build with Next.js. I added the React Simple Dropdown module and am just using the basic sample author provides. All works fine. Now I would like to copy the 3 dropdown files from the module and modify them. So I copied the src files to my components directory and changed my line in my code from:
import Dropdown, { DropdownTrigger, DropdownContent } from 'react-simple-dropdown'
to:
import Dropdown, { DropdownTrigger, DropdownContent } from './Dropdown/Dropdown'
This causes this line to no longer work: if (child.type === DropdownTrigger).
Inspecting the child.type I see a difference (top is my code):
It seems that my Next.js webpack is handling things differently than whatever tool the author use to babelify the original code. I am able to handle the match in other ways but would like to understand what is happening. It seems related so some default export but I am not clear why things are different and what Babel setting handles this.
Evidently class comparison doesn't work with React Hot Loader in dev mode. Known issue with no fix at the moment. So using item.type.displayNane === 'DropdownTrigger' would be a workaround.