Bővítse alkalmazását képfeltöltésekkel

Próbált már blogwebhelyet – vagy csak egy CRUD-webhelyet – létrehozni a MERN-verem segítségével? Szeretett volna képfeltöltést csatolni az alkalmazásához, majd az adatbázisba feltöltött képet megjeleníteni az ügyfélnek?

Hú, ez sok volt. De ma megmutatom, hogyan kell ezt megtenni a Cloudinary és a Multer segítségével.

Felhős

Mi az a Cloudinary, kérdezed?

A Cloudinary egy felhőszolgáltatás, amely lehetővé teszi, hogy egyszerűen töltsön fel képeket a felhőjükbe – amely ezután visszaad egy URL-t, amelyet elmentünk az adatbázisunkba, és megjelenítünk az ügyfélnek.

Ésszerűbb lesz, ha végrehajtjuk. Menjen a www.cloudinary.com oldalra, és hozzon létre fiókot. Ha végzett, feltétlenül vegye le ezeket a hitelesítő adatokat:

Cloud Name, API Key, API Secret

Ezek láthatóak lesznek az irányítópulton. Ezekre később szükségünk lesz, amikor beállítjuk a hátoldalunkat.

React alkalmazás létrehozása

Rendben, kezdjük a kezelőfelület létrehozásával.

Ehhez a create-react-appot fogjuk használni, hogy elindítsunk egy React starter projektet. A create-react-app használatával nem kell aggódnunk a webpack vagy a Babel beállítása miatt (mivel a create-react-app ezt alapértelmezés szerint rendezi).

Ha még nincs globálisan telepítve a Create-React-app a gépeden, akkor be kell írnod…

npm install -g create-react-app

… a termináljába. Ezután a terminálba írja be a következő parancsot:

npm install create-react-app cloudinary-app

A cloudinary-app lesz a projekt neve – bármit elnevezhet, amit csak akar.

Ha ez kész, be kell mennünk a projekt mappába. Ehhez írja be a cd cloudinary-appt a terminálba.

A projekt mappájában írja be a következő parancsot a terminálba: npm start. Ez felpörgeti a fejlesztői szerverünket, és megnyitja a projektjét a localhost:3000 oldalon a böngészőjében.

Mivel már dolgozunk a kezelőfelületünkön, telepítsük a szükséges könyvtárakat. Szükségünk lesz az Axiókra a kezelőfelületen, hogy GET/POST kérést küldhessünk a hátoldalunknak. Használjuk a Reduxot is (annak ellenére, hogy ez egy kis alkalmazás, és a Reactben csak a helyi állapotot használjuk).

Tudom, hogy ezt a legtöbben szeretnék egy nagyobb projektbe bevonni, ezért a Reduxot az államigazgatásra fogom használni. Ehhez írja be a következő parancsot a termináljába.

npm install axios react-redux redux redux-thunk --save

Hozzunk létre néhány fájlt is. Ezek nem szükségesek, de az oktatóanyag követéséhez egyszerűnek kell lenniük.

A src mappában hozzon létre egy history.js fájlt, és másolja ki a következő kódot:

import { createBrowserHistory } from “history”;
export default createBrowserHistory();

Az előzményfájl minden útvonalhoz előzményobjektumot hoz létre kellékként. Ez teljes ellenőrzést biztosít a böngészési előzmények felett. Ez esetünkben akkor hasznos, ha egy művelet után átirányítjuk a felhasználót.

Most a következő fájl, amelyet létrehozunk, egy proxyfájl. Ez megkönnyíti a szerverünkhöz intézett HTTP-kéréseinket. Először hozzunk létre egy összetevő mappát a src mappán belül. Az összetevők mappájában hozzon létre egy AxiosAPI.js fájlt, és illessze be a következő kódot:

import axios from “axios”;
       export default axios.create({
       baseURL: “http://localhost:5000"
          });

Ha valaha is HTTP-kéréseket kellett végrehajtania, tudja, hogy a hosszú URL beírása fájdalmas, így ez sokkal könnyebbé teszi. Rövidesen visszatérünk az összetevők mappájához.

Index.js → Redux Store beállítása

Most csatlakoztassuk Redux üzletünket.

Először menjünk a CRA által már létrehozott Index.js fájlhoz. Ebben a fájlban cserélje ki a kódot a következő kódra. A Redux áruház az összes államunk tárolási helye.

import React from “react”;
import ReactDOM from “react-dom”;
import “./index.css”;
import App from “./App”;
import { Provider } from “react-redux”;
import { createStore, applyMiddleware, compose } from “redux”;
import reducers from “./reducers”;
import reduxThunk from “redux-thunk”;
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
    const store = createStore(reducers,    composeEnhancers(applyMiddleware(reduxThunk)));
ReactDOM.render(<Provider store={store}>
<App />
</Provider>,
document.getElementById(“root”));

Most létre kell hoznunk a reducers és a actions mappánkat.

A src mappában hozzon létre egy reducers és egy actions mappát. Először alakítsuk ki cselekedeteinket. A actions mappában hozzon létre egy új fájlt imageActions.js néven. Ebben a fájlban létrehozzuk a műveleteinket, amelyeket elküldünk a reduktorunknak, hogy elmondják a Reduxnak, hogyan frissítse az alkalmazásunk állapotát.

Műveletek

Mielőtt létrehoznánk a műveletkészítőket, készítsük el a types.js fájlunkat. A actions mappában hozzon létre egy types.js file fájlt. Ez nem kötelező, de mindig jó gyakorlat ezt megtenni arra az esetre, ha elgépelési hibát követne el az akciókészítők létrehozásakor.

Lapozzon át a imageActions.js fájlra. Itt hozzuk létre a actions fájlunkat.

import { ADD_IMAGE, GET_IMAGES, GET_ERRORS } from “./types”;
import AxiosAPI from “../components/AxiosAPI”;
import history from “../history”;
   //ADD IMAGE
    export const addImage = imageData => dispatch => {
    AxiosAPI.post(“/add”, imageData).then(res => dispatch({
    type: ADD_IMAGE,
    payload: res.data
    })).catch(err => dispatch({
    type: GET_ERRORS,
    payload: err.response.data
    }));
   history.push(“/”);
    };
    //GET ALL IMAGES
    export const getAllImages = () => dispatch => {
    AxiosAPI.get(“/”).then(res => dispatch({
    type: GET_IMAGES,
    payload: res.data
    })).catch(err => dispatch({
    type: GET_IMAGES,
    payload: null
       }));
    };

Az átadott imageData a formData, amelyet később az űrlap komponensben fogunk használni, amely a cím és a kép lesz.

Csökkentők

Most állítsuk be a reduktorunkat.

Mivel ez egy kis alkalmazás, csak egy szűkítőnk lesz. De mivel sokan közületek valószínűleg nagyobb alkalmazásokat hoznak létre, több mint egy szűkítő lesz, és a combineReducers értéket kell használnia a rootReducer fájlban.

Mindenesetre a reducers mappánkban létrehozhatunk egy index.js fájlt. A reduktorok csak sima JavaScript objektumok.

Tehát adja hozzá a következő kódot a index.js fájlba. Akkor is hasznos, ha a Redux DevTools szoftvert használja, hogy fizikailag megtekinthesse adatait a Redux áruházban. Másolja a következő kódot a imageActions.js fájlba.

import { ADD_IMAGE, GET_IMAGES } from “../actions/types”;
     const initialState = {
     images: []
      };
     export default function(state = initialState, action) {
       switch (action.type) {
       case ADD_IMAGE:
       return {…state, images: [action.payload, …state.images]};
     case GET_IMAGES:
     return { …state, images: action.payload };
     default:
     return state;
    }
}

Alkatrészek

Kezdjük azzal az űrlappal, amelyet a csatlakozáshoz használnunk kell, hogy a műveletkészítőnket az űrlapösszetevőhöz csatlakoztathassuk.

Hozzon létre egy Form.js nevű fájlt az összetevők mappájában.

import React from “react”;
import { connect } from “react-redux”;
import { addImage } from “../actions/imageActions”;
   class Form extends React.Component {
     constructor(props) {
      super(props);
      this.state = {
      title: “”,
      image: “”
     };
  this.onChangeTitle = this.onChangeTitle.bind(this);
  this.onChangeImage = this.onChangeImage.bind(this);
  this.onSubmit = this.onSubmit.bind(this);
  }
  onChangeTitle = e => {
   this.setState({ title: e.target.value });
   };
  onChangeImage = e => {
   this.setState({ image: e.target.files[0] });
   };
  onSubmit(e) {
  e.preventDefault();
  let formData = new FormData();
  formData.append(“title”, this.state.title);
  formData.append(“image”, this.state.image);
  this.props.addImage(formData);
  
  this.setState({
  title: “”,
  image: “”
  });
 }
  render() {
   return (
   <div className=”form-container”>
   <form encType=”multipart/form-data” onSubmit={this.onSubmit}> 
   <h2>Image Form</h2>
   <label className=”form-label”>Image Title</label>
   <input 
   className=”form-input”
   placeholder=”Enter Image Title”
   type=”text”
   value={this.state.title}
   onChange={this.onChangeTitle}
   />
   <label className=”form-label”>Choose an Image</label>
  <input type=”file” 
  className=”form-input”
  onChange={this.onChangeImage} />
  <button type=”submit” className=”submit-btn”>Submit!</button>
  </form>
  </div>
  );
    }
  }
export default connect(null,{ addImage })(Form);

Az ok, amiért a null az első argumentum a connect függvényben, az az, hogy nem adunk át semmit. Általában a mapStateToProps értéket adjuk át, ahogy az a AllImages.js fájlban is látható.

Így kell kinéznie most az űrlapunknak!

Hozzon létre egy másik fájlt a AllImages.js nevű összetevők alatt. Ez az összetevő felelős az űrlapról a szerverre küldött adatok megjelenítéséért. Ezután vesszük a szerverről visszaérkező adatokat, és megjelenítjük ebben a fájlban. Remélhetőleg ennek van értelme. Íme a AllImages.js kódja:

Minden képünket egy tömbben tároljuk. A getAllImages műveletkészítőt használjuk az adatok kihúzására a tömbből. Ezt úgy tesszük, hogy leképezzük a tömböt, és egyetlen képet ad vissza. A mapStateToProps pontosan azt teszi, amit mond: leképezi az állapotot olyan kellékekre, amelyeket felhasználhatunk a komponensünkben.

Ennyi az alkalmazásunk elején. Most be kell állítanunk a hátoldalunkat, amit a cikk második részében fogunk megtenni.

A cikk 2. részének megtekintése.

Itt van egy link a „GitHub-tárházhoz”.