reactjsaxiosmobxmobx-react

Get data from server using Axios and MobX in React


I need to get the data from the server and save it somewhere so that after re-rendering the LoginsList component, I don't have to request the data from the server again. I decided to start using MobX, but the store function fetchData() just doesn't seem to get called.

For now, the data is accepted in raw form, but then I will use encryption.

store.js

import { makeObservable } from 'mobx';

class store {
    data = []
    isFetching = false
    error = null

    constructor() {
        makeObservable(this, {
            data: observable,
            isFetching: observable,
            error: observable,
            fetchData: action
        })
    }

  fetchData() {
    this.isFetching = true
    axios.get('http://localhost:3001/data')
      .then(response => {
        this.data = response.data
        this.isFetching = false
        console.log('Success');
      })
      .catch(err => {
        this.error = err
        this.isFetching = false
        console.log('Error');
      })
  }
}

export default store;

LoginsList.js

import React, { useState, useEffect } from 'react';
import classNames from 'classnames';
import { Observer } from 'mobx-react-lite';
import store from '../.store/data';

import LoginDetails from './LoginDetails';
import Login_Icon from '../assets/icons/Login.svg'
import '../assets/css/LoginCards.css'

const LoginsList = () => {
  const [activeTab, setActiveTab] = useState(0);
  const [hoveredTab, setHoveredTab] = useState(null);

  const handleMouseEnter = (index) => {
    if (index !== activeTab) {
        setHoveredTab(index);
    }
  }

  const handleClick = (index) => {
    setHoveredTab(null);
    setActiveTab(index);
  }

  useEffect(() => {
    store.fetchData();
  }, []);

  return (
    <>
    <Observer>
      <ul>
        {store.data.map((card, index) => (
          <li
            key={card.id} 
            onClick={() => handleClick(index)}
            onMouseEnter={() => handleMouseEnter(index)}
            onMouseLeave={() => setHoveredTab(null)}
            className="LoginCard"
          >
            <div
              className={classNames('LoginCardContainer', { 'active-logincard': index === activeTab }, { 'hovered-logincard': index === hoveredTab })}
            >
                <img src={Login_Icon} alt="Login Icon"></img>
                <div className="TextZone">
                    <p>{card.name}</p>
                    <div>{card.username}</div>
                </div>
            </div>
          </li>
        ))}
      </ul>
      <div>
        <div className="LoginDetails">
          <img className="LoginDetailsIcon" src={Login_Icon}></img>
        </div>
          <LoginDetails key={activeTab} name={store.data[activeTab].name} username={store.data[activeTab].username} password={store.data[activeTab].password}/>
          {store.data[activeTab].password} 
      </div>
      </Observer>
    </>

  );
}

export default LoginsList;

I tried creating a store, importing it into the LoginsList component and getting the data. In the browser console, I saw an error Uncaught TypeError: _store_data__WEBPACK_IMPORTED_MODULE_3__.default.data is undefined

If I open http://localhost:3001/data in my browser, I can easily read the data. I don't think the error is on the server side.


Solution

  • I solved the problem. All I had to do was use makeAutoObservable instead of makeObservable.

    import { action, makeAutoObservable } from 'mobx';
    import axios from 'axios';
    
    class UserData {
        data = []
        isFetching = false
        error = null
    
        constructor() {
            makeAutoObservable(this)
        }
    
      fetchData() {
        this.isFetching = true
        axios.get('http://localhost:3001/data')
          .then(response => {
            this.data = response.data
            this.isFetching = false
            console.log('Success');
          })
          .catch(err => {
            this.error = err
            this.isFetching = false
            console.log('Error');
          })
      };
    }
    
    export default new UserData;