Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React Hooks (useState) and Mobx [No mobx-react-lite]

in my react application (with typescript) I want to use React hooks (specifically useState) to manage the form state and meanwhile use it as an observable component for Mobx store but I get the error

Hooks can only be called inside the body of a function component.

so for instance in the following component

import * as React from "react";
import { inject, observer } from "mobx-react";
import { MyStore } from "./MyStore";

interface IProps {
  myStore?: MyStore;
  id: string;
}

const MyComponent: React.FC<IProps> = props => {
  const [state, setState] = React.useState("");
  return (
    <div>
      <h1>{props.id}</h1>
    </div>
  );
};
export default inject("myStore")(observer(MyComponent));

I saw a solution but that was using React.createContext for exporting the store class. is not where the old approach for Mobx and Hooks?

here is the sanbox for the example

like image 422
Amir-Mousavi Avatar asked Mar 25 '19 02:03

Amir-Mousavi


People also ask

Can you use Hooks with MobX?

Hooks to the rescue. React Hooks are most likely the easiest way to consume MobX store.

Is MobX deprecated?

https://github.com/mobxjs/mobx/ is now monorepo with all the packages, so nothing is deprecated.

Is MobX better than redux?

2. Debug process: Compared to MobX, debugging in Redux is a better experience because it has more developer tools and less abstraction. The Redux becomes more predictable with the flux paradigm. Debugging in MobX is much more difficult due to increased abstraction and average developer tools.


Video Answer


2 Answers

Thanks to @Tholle mentioning the Mobx version, now that the Mobx 6 is released this question is solved

like image 96
Amir-Mousavi Avatar answered Nov 01 '22 10:11

Amir-Mousavi


mobx-react doesn't support hooks and if you wish to use hooks with mobx you need to make use of mobx-react-lite which is also mentioned in the github documentation

To do that you can make use of React.createContext instead of provider and useContext instead of inject

Index.tsx

import * as React from "react";
import { render } from "react-dom";
import MyComponent, { Store } from "./MyComponent";

import "./styles.css";
import MyStore from "./MyStore";

function App() {
  const [state, setState] = React.useState("");
  return (
    <Store.Provider value={MyStore}>
      <div className="App">
        <MyComponent id={"someID"} />
      </div>
    </Store.Provider>
  );
}

const rootElement = document.getElementById("root");
render(<App />, rootElement);

MyComponent.tsx

import * as React from "react";
import { Observer } from "mobx-react-lite";
import { MyStore } from "./MyStore";

interface IProps {
  myStore?: MyStore;
  id: string;
}

export const Store = React.createContext();
const MyComponent: React.FC<IProps> = props => {
  const [state, setState] = React.useState("");
  const store = React.useContext(Store);
  console.log(state, store);
  return (
    <div>
      <h1>{props.id}</h1>
    </div>
  );
};
export default MyComponent;

Working demo

like image 20
Shubham Khatri Avatar answered Nov 01 '22 08:11

Shubham Khatri