Very simple app, I'm trying to display content from my API using Mobx and Axios, here's my Axios agent.ts:
import { ITutorialUnit } from './../model/unit';
import axios, { AxiosResponse } from "axios";
//set the base URL
axios.defaults.baseURL = "http://localhost:5000/api";
//store our request in a const
const responseBody = (response: AxiosResponse) => response.data;
const requests = {
get: (url: string) => axios.get(url).then(responseBody),
};
//create a const for our activty's feature,all our activities' request are go inside our Activities object
const TutorialUnits = {
list: ():Promise<ITutorialUnit[]> => requests.get("/tutorialunits"),
};
export default{
TutorialUnits
}
then I call this agent.s in a store:
import { ITutorialUnit } from "./../model/unit";
import { action, observable } from "mobx";
import { createContext } from "react";
import agent from "../api/agent";
class UnitStore {
@observable units: ITutorialUnit[] = [];
//observable for loading indicator
@observable loadingInitial = false;
@action loadUnits = async () => {
//start the loading indicator
this.loadingInitial = true;
try {
//we use await to block anything block anything below list() method
const units = await agent.TutorialUnits.list();
units.forEach((unit) => {
this.units.push(unit);
// console.log(units);
});
this.loadingInitial = false;
} catch (error) {
console.log(error);
this.loadingInitial = false;
}
};
}
export default createContext(new UnitStore());
then I call this in my App
component:
import React, { Fragment, useContext, useEffect } from "react";
import { Container } from "semantic-ui-react";
import "semantic-ui-css/semantic.min.css";
import NavBar from "../../features/nav/NavBar";
import { ActivityDashboard } from "../../features/Units/dashboard/tutorialUnitDashboard";
import UnitStore from "../stores/unitStore";
import { observer } from "mobx-react-lite";
import { LoadingComponent } from "./LoadingComponent";
const App = () => {
const unitStore = useContext(UnitStore);
useEffect(() => {
unitStore.loadUnits();
//need to specify the dependencies in dependenciy array below
}, [unitStore]);
//we are also observing loading initial below
if (unitStore.loadingInitial) {
return <LoadingComponent content="Loading contents..." />;
}
return (
<Fragment>
<NavBar />
<Container style={{ marginTop: "7em" }}>
<ActivityDashboard />
</Container>
</Fragment>
);
};
export default observer(App);
Finally, I want to use this component to display my content:
import { observer } from "mobx-react-lite";
import React, { Fragment, useContext } from "react";
import { Button, Item, Label, Segment } from "semantic-ui-react";
import UnitStore from "../../../app/stores/unitStore";
const UnitList: React.FC = () => {
const unitStore = useContext(UnitStore);
const { units } = unitStore;
console.log(units)
return (
<Fragment>
{units.map((unit) => (
<h2>{unit.content}</h2>
))}
</Fragment>
);
};
export default observer(UnitList);
I can't see the units.. Where's the problem? My API is working, I tested with Postman. Thanks!!
If you were using MobX 6 then you now need to use makeObservable
method inside constructor to achieve same functionality with decorators as before:
class UnitStore {
@observable units: ITutorialUnit[] = [];
@observable loadingInitial = false;
constructor() {
// Just call it here
makeObservable(this);
}
// other code
}
Although there is new thing that will probably allow you to drop decorators altogether, makeAutoObservable
:
class UnitStore {
// Don't need decorators now anywhere
units: ITutorialUnit[] = [];
loadingInitial = false;
constructor() {
// Just call it here
makeAutoObservable(this);
}
// other code
}
More info here: https://mobx.js.org/react-integration.html