فهرست منبع

react-express-mongodb: clean frontend code

- apply prettier style on every js file
- remove mutation on immutable variables
- remove wrapper on top of axios
- fix form handling
- remove useless port definition in dockerfile

Signed-off-by: Jérémie Drouet <jeremie.drouet@gmail.com>
Jérémie Drouet 5 سال پیش
والد
کامیت
e5828ad1bf

+ 0 - 1
react-express-mongodb/.dockerignore

@@ -1 +0,0 @@
-server/node_modules

+ 1 - 0
react-express-mongodb/backend/.dockerignore

@@ -0,0 +1 @@
+node_modules

+ 7 - 20
react-express-mongodb/backend/Dockerfile

@@ -1,27 +1,14 @@
-FROM node:13.13.0-stretch-slim
-
-#Argument that is passed from docer-compose.yaml file
-ARG NODE_PORT
-
-#Echo the argument to check passed argument loaded here correctly
-RUN echo "Argument port is : $NODE_PORT"
+FROM node:lts-buster-slim
 
 # Create app directory
 WORKDIR /usr/src/app
 
-#COPY . .
-COPY . .
-
-# Install app dependencies
-# A wildcard is used to ensure both package.json AND package-lock.json are copied
-# where available (npm@5+)
-RUN npm install
-
-
-#In my case my app binds to port NODE_PORT so you'll use the EXPOSE instruction to have it mapped by the docker daemon:
-
-EXPOSE ${NODE_PORT}
+COPY package.json /usr/src/app/package.json
+COPY package-lock.json /usr/src/app/package-lock.json
+RUN npm ci
 
-CMD npm run dev
+COPY . /usr/src/app
 
+EXPOSE 3000
 
+CMD [ "npm", "run", "dev" ]

+ 3 - 9
react-express-mongodb/docker-compose.yml

@@ -1,12 +1,9 @@
 version: "3.7"
 services:
   frontend:
-    build:
-      context: frontend
-      args:
-        FRONT_END_PORT: 5000
+    build: frontend
     ports:
-      - 5000:5000
+      - 3000:3000
     stdin_open: true
     volumes:
       - ./frontend:/usr/src/app
@@ -21,10 +18,7 @@ services:
   backend:
     container_name: backend
     restart: always
-    build:
-      context: backend
-      args:
-        NODE_PORT: 3000
+    build: backend
     volumes:
       - ./backend:/usr/src/app
       - /usr/src/app/node_modules

+ 0 - 1
react-express-mongodb/frontend/.dockerignore

@@ -1,3 +1,2 @@
 node_modules
 npm-debug.log
-server/logs/

+ 2 - 8
react-express-mongodb/frontend/Dockerfile

@@ -1,15 +1,9 @@
 # Create image based on the official Node image from dockerhub
-FROM node:13.13.0-stretch
-
-#Argument that is passed from docer-compose.yaml file
-ARG FRONT_END_PORT
+FROM node:lts-buster-slim
 
 # Create app directory
 WORKDIR /usr/src/app
 
-#Echo the argument to check passed argument loaded here correctly
-RUN echo "Argument port is : $FRONT_END_PORT"
-
 # Copy dependency definitions
 COPY package.json /usr/src/app
 COPY package-lock.json /usr/src/app
@@ -24,7 +18,7 @@ RUN npm ci
 COPY . /usr/src/app
 
 # Expose the port the app runs in
-EXPOSE ${FRONT_END_PORT}
+EXPOSE 3000
 
 # Serve the app
 CMD ["npm", "start"]

+ 34 - 35
react-express-mongodb/frontend/src/App.js

@@ -1,56 +1,55 @@
-import React from 'react';
-import {request} from './utilities/httpRequestHandler'
-import './App.scss';
+import React from "react";
+import axios from "axios";
+import "./App.scss";
 import AddTodo from "./components/AddTodo";
 import TodoList from "./components/TodoList";
 
-export default class App extends React.Component{
-
-  constructor(props){
+export default class App extends React.Component {
+  constructor(props) {
     super(props);
 
     this.state = {
-      todos: []
-    }
+      todos: [],
+    };
   }
 
   componentDidMount() {
-      request('get','/api')
-          .then((response) => {
-              this.setState({
-                  todos: response.data.data
-              })
-          }).catch((e) => console.log('Error : ', e))
+    axios
+      .get("/api")
+      .then((response) => {
+        this.setState({
+          todos: response.data.data,
+        });
+      })
+      .catch((e) => console.log("Error : ", e));
   }
 
-    _handleAddTodo = (value) => {
-      request('post', '/api/todos', {text:value})
-          .then((response) => {
-              let todosCopy = this.state.todos;
-              todosCopy.unshift({text:value});
-              this.setState({
-                  todos : todosCopy
-              });
-              this.refs.todo.value = ""
-          }).catch((e) => console.log('Error : ', e));
-    };
-
+  handleAddTodo = (value) => {
+    axios
+      .post("/api/todos", { text: value })
+      .then(() => {
+        this.setState({
+          todos: [...this.state.todos, { text: value }],
+        });
+      })
+      .catch((e) => console.log("Error : ", e));
+  };
 
   render() {
     return (
-        <div className="App container">
-          <div className="container-fluid">
-            <div className="row">
-              <div className="col-xs-12 col-sm-8 col-md-8 offset-md-2">
-                <h1>Todos</h1>
-                  <div className="todo-app">
-                      <AddTodo handleAddTodo={(value) => {this._handleAddTodo(value)}}/>
-                      <TodoList todos={this.state.todos}/>
-                  </div>
+      <div className="App container">
+        <div className="container-fluid">
+          <div className="row">
+            <div className="col-xs-12 col-sm-8 col-md-8 offset-md-2">
+              <h1>Todos</h1>
+              <div className="todo-app">
+                <AddTodo handleAddTodo={this.handleAddTodo} />
+                <TodoList todos={this.state.todos} />
               </div>
             </div>
           </div>
         </div>
+      </div>
     );
   }
 }

+ 30 - 19
react-express-mongodb/frontend/src/components/AddTodo.js

@@ -1,22 +1,33 @@
-import React from 'react';
+import React from "react";
 
 export default class AddTodo extends React.Component {
-
-    _onAddTodo = () => {
-        if(this.refs.todo.value.length > 0) {
-            this.props.handleAddTodo(this.refs.todo.value);
-            this.refs.todo.value = '';
-        }
-    };
-
-    render() {
-        return (
-            <div className="new-todo form-group">
-                <input type="text" className="form-control" ref="todo"/>
-                <button className="btn btn-primary" onClick={this._onAddTodo}>
-                    Add Todo
-                </button>
-            </div>
-        )
+  handleSubmit = (e) => {
+    e.preventDefault();
+    const { value } = e.target.elements.value;
+    if (value.length > 0) {
+      this.props.handleAddTodo(value);
+      e.target.reset();
     }
-}
+  };
+
+  render() {
+    return (
+      <form
+        noValidate
+        onSubmit={this.handleSubmit}
+        className="new-todo form-group"
+      >
+        <input
+          type="text"
+          name="value"
+          required
+          minLength={1}
+          className="form-control"
+        />
+        <button className="btn btn-primary" type="submit">
+          Add Todo
+        </button>
+      </form>
+    );
+  }
+}

+ 43 - 42
react-express-mongodb/frontend/src/components/TodoList.js

@@ -1,48 +1,49 @@
-import React from 'react';
+import React from "react";
 
 export default class TodoList extends React.Component {
+  constructor(props) {
+    super(props);
 
-    constructor(props){
-        super(props);
+    this.state = {
+      activeIndex: 0,
+    };
+  }
 
-        this.state = {
-            activeIndex:0,
-        }
-    }
+  handleActive(index) {
+    this.setState({
+      activeIndex: index,
+    });
+  }
 
-    _handleActive(index) {
-        this.setState({
-            activeIndex: index
-        })
-    }
+  renderTodos(todos) {
+    return (
+      <ul className="list-group">
+        {todos.map((todo, i) => (
+          <li
+            className={
+              "list-group-item cursor-pointer " +
+              (i === this.state.activeIndex ? "active" : "")
+            }
+            key={i}
+            onClick={() => {
+              this.handleActive(i);
+            }}
+          >
+            {todo.text}
+          </li>
+        ))}
+      </ul>
+    );
+  }
 
-    _renderTodos(todos) {
-        return (
-            <ul className="list-group">
-                {
-                    todos.map((todo, i) => {
-                        return (<li className={'list-group-item cursor-pointer ' + (i===this.state.activeIndex ? 'active' : '')}
-                                    key={i}
-                                    onClick={() => {this._handleActive(i)}}
-                        >
-                            {todo.text}
-                        </li>)
-                    })
-                }
-            </ul>
-        )
-    }
-
-
-    render() {
-        let { todos } = this.props;
-        return (
-            todos.length > 0 ?
-                this._renderTodos(todos)
-                :
-                <div className="alert alert-primary" role="alert">
-                    No Todos to display
-                </div>
-        )
-    }
-}
+  render() {
+    let { todos } = this.props;
+    return todos.length > 0 ? (
+      this.renderTodos(todos)
+    ) : (
+      <div className="alert alert-primary" role="alert">
+        No Todos to display
+      </div>
+    );
+  }
+}

+ 0 - 16
react-express-mongodb/frontend/src/utilities/httpRequestHandler.js

@@ -1,16 +0,0 @@
-import axios from 'axios';
-
-
-export function request (method, uri, data, headers = null, params = null) {
-    let query = {
-        method,
-        url: uri
-    };
-    if (headers !== null)
-        query.headers = headers;
-    if (params !== null)
-        query.params = params;
-    if (method === 'post' || method === 'put' || method === 'delete' || method === 'patch')
-        query.data = data;
-    return axios(query);
-}