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 (
// ...
);
};
Related
Hi people 🙂 I am doing a project with React + JS and I have installed wouter and I am trying to make my app working with a dynamic params in the route. That means: if I go to "/gif/panda" that it will render the gifs of pandas. However, although I have been several hours researching, I dont know what happens. As you can see in console, the "/gif/:keyword/", I mean, the keyword is received by the component List of Gifs, as it returns the phrase "Hola Panda". Panda was the keyword. But I dont know why the return code of the component is unreacheable and, therefore, the app crashes. Any idea? Thanks.
You must put JSX code into brackets on return statement.(in ListofGifs component)
Since there is no brackets your function returns nothing. If you look carefully you can see that the code after return statement is pale which means it just doesn't work. I added image below. I hope it solves problem.
add brackets
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'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.
I'm taking a foray into Firefox extension development for the first time, and so far it's been pretty comfortable going, but I'm running into a problem; one of the things I need to do overwriting the built-in nsIPromptService and replacing it with something of my own instead.
I walked through the basic XPCOM component creation tutorial here and got the hello world one working:
https://developer.mozilla.org/en/creating_xpcom_components
And everything in that seems to work fine, but nothing I've been able to find or research shows how I can overwrite an interface from javascript. I've seen things in C++ and Java that seem to be able to overwrite the built-in components, but I can't find anything about doing this from javascript, and just trying to change the contract ID didn't work; when I try to get the service from the contract ID (as below), it just returns the original, built-in component version.
var myComponent = Components.classes['#mozilla.org/embedcomp/prompt-service;1']
.getService(Components.interfaces.nsIPromptService);
Is there something really obvious here that I'm missing? Is this the wrong way to go about overriding components (I can't seem to find anything anywhere, so I'm not really sure what I should be doing..).
Neil, thanks for the suggestion. That's what I thought I was doing (and I was), but if you're actually overriding a contract (instead of defining a new one), it looks like the answer is that you have to go to the nsIComponentRegistrar and actually register your factory (rather than relying on the chrome.manifest to handle it for you). An example of this would be:
Components.manager.nsIComponentRegistrar.registerFactory(CLASS_ID, CLASS_NAME, CONTRACT_ID, MyPromptServiceFactory);
Where the constans were:
const CLASS_ID = Components.ID("{a2112d6a-0e28-421f-b46a-25c0b308cbd0}");
// description
const CLASS_NAME = "My Prompt Service";
// textual unique identifier
const CONTRACT_ID = "#mozilla.org/embedcomp/prompt-service;1";
Where the CLASS_ID/CONTRACT_ID were the IDs for the pre-existing service.
You need to register your component using the contract id of the service that you want to override.