MOBX and react integration - reactjs

getting in valid hook error in a re write of a clients app... (upgrading code)
mobx 6.3.8 mobx react 7.2.1 and mobx-state-tree 5.0.5
React 17.0.1 RN 0.64.3
i feel like the error is here. i googled the code line for use stores and it led me to the deprecated site... i dont know where to find new handling in the https://mobx.js.org/react-integration.html site... what would this be called?
import { createContext, useContext } from "react"
import { RootStore } from "./root-store"
const RootStoreContext = createContext<RootStore>({} as RootStore)
const RootStoreProvider = RootStoreContext.Provider
// hook error here? // export const useStores = () => useContext(RootStoreContext);
error:
Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
You might have mismatching versions of React and the renderer (such as React DOM)
You might be breaking the Rules of Hooks
You might have more than one copy of React in the same app
See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.
adding more context... rootstore file
import { Instance, SnapshotOut, types } from "mobx-state-tree"
import { creatMediaPlayerModel } from "../../models/media-player"
import { createUserModel } from "../../models/user"
import { createContentModel } from "../../models/content"
export const RootStoreModel = types.model("RootStore", {
mediaPlayerStore: creatMediaPlayerModel(),
userStore: createUserModel(),
contentStore: createContentModel(),
})
export type RootStore = Instance<typeof RootStoreModel>
export type RootStoreSnapshot = SnapshotOut<typeof RootStoreModel>

From that error message:
Hooks can only be called inside of the body of a function component.
You are not calling a hook from inside the body of a function component. So you are breaking the rules of hooks.
According the rules of hooks you can only call a hook from the top level of a react function component. If you are not inside a functional component, then you cannot use a react hook*.
From the docs:
Don’t call Hooks inside loops, conditions, or nested functions. Instead, always use Hooks at the top level of your React function, before any early returns. By following this rule, you ensure that Hooks are called in the same order each time a component renders. That’s what allows React to correctly preserve the state of Hooks between multiple useState and useEffect calls.
That means you need to call useStores from within a functional component.
Something like:
function MyComponent() {
const myStores = useStores()
// render component with data from stores here
return <>{myStore.myData}</>
}
* The exception, sort of, is a custom hook which can call other hooks. Your useStores here is a custom hook. So it's fine to call useContext from that custom hook.
But that custom hook must obey the same usage rules as the built in hooks, so all hooks are called from the body of a function component, there is just function in between.

Related

Why I can't use Hooks in React class components' render method

In my mental model, React function components are basically class components stripped down to render method (and this is reinforced by React docs saying that that render should be a pure function of state and props). I assume that render method and Functional components are called at the same phase of React lifecycle so why I can't use hooks in render method? To be more precise, I want to know the technical limitations of class components which disallow hooks usage.
import React from "react";
export default class App extends React.Component {
render() {
const [state, setState] = React.useState(0); // Invalid hook call. Hooks can only be called inside of the body of a function component.
return (
<div>
<h1>Hello World</h1>
</div>
);
}
}
no, we can't use hooks with class component. So, please, read the documentation
Rules of hooks:
✅ Call Hooks from React function components.
✅ Call Hooks from custom Hooks (we’ll learn about them on the next page).

React Hook "useState" is called in function "test" which is neither a React function component or a custom React Hook function

I am trying to use React useState hook in my functional component but I am getting this error:
Failed to compile
./src/Person/Person.js
Line 5:43: React Hook "useState" is called in function "person" which is neither a React function component or a custom React Hook function react-hooks/rules-of-hooks
Search for the keywords to learn more about each error.
This error occurred during the build time and cannot be dismissed.
Here is the code for the same:
import React, {useState} from 'react';
import { tsPropertySignature, directive } from '#babel/types';
const person =props =>{
const [initState,stateChangeFunction]=useState({name:'akie#123'})
return <p>I am from the {}</p>
}
export default person;
Thanks in advance.
react recognize capitalized function name as a react function component, in your case
function Person () {}
for more, react aslo recognize function name begin with 'use' as custom hook,like
function usePeople() {}
and hooks ONLY avaliable in a function component or a custom hook
Your Component name should be capitalise it should look like this :-
const Person = () => {
// .......
}
export default Person;

Why does React think I'm not calling `useState` "inside the body of a function component"?

I have a React app in Typescript where I'm trying to use the useState hook in one section and running into trouble. I've reduced the code to the following minimal example:
projects-loader.tsx:
import React from "react";
import { render } from "react-dom";
import MoreProjectsTable from "./components/MoreProjectsTable";
export const projects = (): void => {
const moreProjectsRootEl = document.getElementById(
"react-more-projects-table-root"
);
render(<MoreProjectsTable/>, moreProjectsRootEl);
};
export default projects;
MoreProjectsTable.tsx:
import React, { ReactElement, useState } from "react";
import MoreProjectsRow from "./MoreProjectsRow";
const MoreProjectsTable = (): ReactElement<HTMLElement> => {
useState();
return (<div/>);
};
export default MoreProjectsTable;
But when I call projects() it fails with the error "Hooks can only be called inside the body of a function component."
I understand from research that there are three common reasons for this error:
Violating the Rules Of Hooks
Mismatching versions of React and React-DOM
Multiple copies of React in the same app
Regarding #1, I don't see where I'm violating the Rules Of Hooks--it looks to me like I'm calling useState from the top-level of a function component, all right.
Regarding #2, I verified that React and React-DOM are both v16.8.1.
Regarding #3, I verified via the method described on this page that that is not the case.
Can anyone suggest anything else I might try? I'm very new to React so no suggestion is too obvious.
About one minute after I posted this question, a co-worker figured it out. This app is running on a Web page and, without noticing it, I was loading the top-level script itself from two different places. A variation on scenario #3 then, apparently.

Getting a Cannot update during an existing state transition message after library updates

Have a ReactJS + Redux + Saga application that was recently updated to use the latest (or close to latest) versions of the respective JS libraries. After the library updates (no code changes) and running the application, I immediately see the "Cannot update during an existing state transition (such as within render). Render methods should be a pure function of props and state." warning message in the console. It looks to be triggered by redux when I invoke the dispatch function (which then calls a function in Provider.js, then goes through react-dom, and then in turn writes the warning message. Again nothing in my code has changed, and my code is essentially built using stateless functions.
Not sure how to go about figuring out what is causing this warning-- although the app still runs ok as expected. Using React 16.8.6, react-redux 6.0.1, react-router-dom 5.0.0, redux 4.0.1, redux-saga 1.0.2, and connected-react-router 6.4.0.
Below is a sample page that would cause the warning message:
import React from 'react'
import {connect} from 'react-redux'
import {links} from '../links'
import {notify} from '../notifications'
const Home = props => {
const {dispatch} = props
return (
<main>
<p>
Go to Details...
</p>
</main>
)}
const dispatcher = dispatch => {
dispatch(notify(links.HOME))
return {dispatch}
}
export default connect(null, dispatcher)(Home)
You cannot call to dispatch inside the disaptcher function.
react-redux's connect parameters are:
function connect(mapStateToProps?, mapDispatchToProps?, mergeProps?, options?)
mapDispatchToProps is what you called dispatch. These params are eventually run as functions that called in the render loop of the connected component. When you dispatch in the render loop it changes the state of a React component (looks like it's the Provider), which is forbidden by React.
Solution
Move the dispatch(notify(links.HOME)) to lifecycle method. For example you can add to the Home component (this will require to rewrite the Home component as an extension of React.Component class:
componentDidMount() {
dispatch(notify(links.HOME))
}
UPDATE
If you want to do this with classless component see that question

ReactJS useCallback not a function of react?

I have a functional Component which is using the hook useCallback. For the last few days everything was just fine. All worked as it should. Today I start up the app and I have this error:
React Hook "useCallback" is called in function "loginPage" which is neither a React function component or a custom React Hook function
This makes no sense because it has been fine. For debugging I simply erased all code on the page except that one coed and even just put a useCallback template in its place, but still the same. It is as if it has been removed from react entirely.
I checked my react version and find 16.8.6 also in react-dom.
Does anyone have any ideas?
import React, {Fragment,useCallback } from 'react';
import { Redirect} from 'react-router-dom';
import {useDropzone} from 'react-dropzone';
const loginPage = (props) => {
const callbackFunction = useCallback(() => {
console.log("callback called");
// Do something with callbackCount ...
return true;
}, []);
}
I see three problems why the error occurred.
which is neither a React function component or a custom React Hook function
loginPage is not a component. useCallback is a hook and it needs to be called inside a function component (not a class component) or in another hook (a function whose name starts with "use"). Check out the rules of hooks.
And also the component name should start with a capital letter, so it should be LoginPage for it to be a valid React component.
You are not returning anything from your component.

Resources