1

I am developing react app for some time. The application was initially created using a Create-React-App command.

I came to the phase when I need to implement a form where the user could manually add a person if he can't find it via AutoComplete Input. All persons are stored in persons.js File which is located in src/components/lists and looks like this:

    const persons = [
        { name: "Person 1", id: "1" },
        { name: "Person 2", id: "2" },
        { name: "Person 3", id: "3" },
        ...];
    // Export
    export { persons };

When the user is adding a new person through the form it should permanently (visible for other users), means, I need to change file persons.js and don't want to use localstorage.

With my modest knowledge I came to the conclusion that I need to use say Express.js I installed (along with Axios) and tried to implement form

Addperson.js is located in src/components/other and looks like this:

import React, { useState } from 'react';
import axios from 'axios';

function Addperson() {
  const [name, setName] = useState('');
  const [id, setId] = useState('');

  const handleSubmit = async (e) => {
    e.preventDefault();

    try {
      const res = await axios.post('/api/persons', { name, id });
      console.log(res.data);
    } catch (err) {
      console.error(err);
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <label>
        Ime:
        <input type="text" value={name} onChange={(e) => setName(e.target.value)} />
      </label>
      <br />
      <label>
        ID:
        <input type="text" value={id} onChange={(e) => setId(e.target.value)} />
      </label>
      <br />
      <button type="submit">Add Person</button>
    </form>
  );
}

export default Addperson;

Server.js is in the app root:

const express = require('express');
const bodyParser = require('body-parser');
const { persons } = require('./src/components/lists/persons');
const app = express();
const port = 5000;

app.use(bodyParser.json());

app.post('/api/persons', (req, res) => {
  const { name, id } = req.body;

  persons.push({ name, id });

  res.json(persons);
});

app.listen(port, () => {
  console.log(`Server is listening on port ${port}`);
});

package.json:

{
  "name": "firstapp",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@fortawesome/fontawesome-svg-core": "^6.2.0",
    "@fortawesome/free-brands-svg-icons": "^6.1.1",
    "@fortawesome/free-regular-svg-icons": "^6.2.0",
    "@fortawesome/free-solid-svg-icons": "^6.2.0",
    "@fortawesome/react-fontawesome": "^0.2.0",
    "@testing-library/jest-dom": "^5.16.4",
    "@testing-library/react": "^13.1.1",
    "@testing-library/user-event": "^13.5.0",
    "axios": "^1.3.3",
    "babel-plugin-macros": "^3.1.0",
    "bootstrap": "^5.1.3",
    "bootstrap-icons": "^1.10.3",
    "date-fns": "^2.29.3",
    "express": "^4.18.2",
    "file-saver": "^2.0.5",
    "firebase": "^9.15.0",
    "fs": "^0.0.1-security",
    "html-docx-js": "^0.3.1",
    "html-react-parser": "^3.0.7",
    "react": "^18.1.0",
    "react-bootstrap": "^2.3.1",
    "react-bootstrap-icons": "^1.10.2",
    "react-datepicker": "^4.8.0",
    "react-dom": "^18.1.0",
    "react-router-dom": "^6.4.5",
    "react-scripts": "5.0.1",
    "react-select": "^5.4.0",
    "web-vitals": "^2.1.4"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}

React app (client) works well, but looks like I can't get working express server.js.

When I try to run node server.js I got:

C:\Users\xxxx\Desktop\web\firstapp\src\components\lists\persons.js:62        
    export { persons };
    ^^^^^^

    SyntaxError: Unexpected token 'export'

When I try to submit user I got:

xhr.js:247 POST http://localhost:3000/api/persons 404 (Not Found)

Does anyone perhaps see any obvious error in the settings? Any help is welcome. Thanks

Jason Aller
  • 3,541
  • 28
  • 38
  • 38
ribosed
  • 128
  • 1
  • 11

1 Answers1

0

You just cannot import a React component from Express like this, then try to modify a variable and have other users on the app see that change. You've graduated to at least needing a database.

I highly recommend jumping into Firebase to utilize the Firestore because you can store your Persons array of objects then simply create a Firestore "listener" that every React user's UI would see when changes are made to the Persons object inside Firestore.

Get realtime updates with Cloud Firestore

Otherwise you're looking at setting up something like MySQL + Websockets.

Additionally, if you must just directly edit a local backend file that is shared between clients, you can use fs.

To read data:

const fs = require('fs');

let json = fs.readFileSync('random.json');
let data = JSON.parse(json);

console.log(data);

Writing a file:

const fs = require('fs');

const data = { 
  foo: 'bar'
};
 
const jsonString = JSON.stringify(data

fs.writeFileSync('random.json', jsonString);
Wesley LeMahieu
  • 2,296
  • 1
  • 12
  • 8
  • 1
    So, for now there is no option to make app work without any "external" database? The changes dont need to be visible instantly for other users but after reloading the page. For me, best option would be to have app with data stored on persons.js or .json file ... It would be great if i could implement form that woud modify the persons array for future use ... I will consider your suggestion ... Thank you! – ribosed Feb 20 '23 at 22:35
  • The other option which isn't scalable but is possible is to use `fs` to read/write to a backend `.json` file. This thread covers that --- https://stackoverflow.com/questions/36856232/write-add-data-in-json-file-using-node-js --- Also added an example to the answer on how to read/write with `fs`. – Wesley LeMahieu Feb 20 '23 at 22:39