آموزش استفاده از axios در ری اکت و نود جی اس

آموزش استفاده از axios در ری اکت و نود جی اس

آموزش استفاده از axios در ری اکت و نود جی اس

using Axios in react and node js

توسط : admin
در این آموزش با شما هستیم به نحوه ارسال و دریافت اطلاعات یک اپلیکیشن ری اکت با سرور ، توسط کتابخانه بی نظیر و پرکاربرد axios آشنا بشیم .

مطالبی که در آموزش ری اکت قصد داریم پیاده سازی کنیم به شرح زیر است :

 

شرح کدهای سمت سرور ، قبلا در آموزش انجام عملیات اصلی بر روی دیتا بیس مونگو دی بی  توسط نود جی اس ، بیان شده اند . برای اینکه در وقت صرفه جویی کنیم  فقط به شرح  کد های سمت کلاینت و ماژول جدید cors در سمت سرور میپردازیم . در پایان این آموزش هر دو پروژه سمت سرور و کلاینت رو میتونید به صورت مجزا دانلود کنید .

ما جدول فرضی برای فرم تماس با ما داریم که شامل 4 فیلد زیر میشه :

  1. email
  2. title
  3. comment
  4. insertDate

 

کدهای سمت سرور :

در سمت سرور پروژه ای با نام server-side ایجاد کنید و ابتدا دستور زیر رو برای ایجاد فایل package.json اجرا کنید :

npm init 

 

ماژول های زیر رو در پروژه نصب کنید :

npm i mongoose express cors body-parser

 

فایل ارتباط به دیتا بیس مونگو دی بی رو با محتویات زیر به نام mongoose.js به پروژه اضافه کنید :

const mongoose = require("mongoose");
const fs = require("fs");
//_NILOOTECH

const connectionString = "mongodb://localhost:27017/test-db";
//const connectionString = "mongodb://username:password@domainname:27017/yourdatabasename";
mongoose.Promise = global.Promise;
mongoose
  .connect(connectionString, {
    useNewUrlParser: true,
    useFindAndModify: false,
    reconnectTries: Number.MAX_VALUE,
    reconnectInterval: 1000,
    useCreateIndex: true
  })
  .then(() => {
    fs.writeFile("message.txt", "connected success", err => {
      if (err) throw err;
      console.log("The file has been saved!");
    });
  })
  .catch(ex => {
    fs.writeFile("error.txt", "connected un success", err => {
      if (err) throw err;
      console.log("The file has been saved!");
    });
  });
module.exports = {
  mongoose
};

 

فایل contact.js رو برای ایجاد مدل جدول با محتویات زیر به پروژه اضافه کنید :

const { mongoose } = require("./mongoose");

let contactSchema = new mongoose.Schema({
  email: {
    type: String,
    minlength: 5,
    maxlength: 255,
    required: true
  },
  title: {
    type: String,
    minlength: 5,
    maxlength: 150,
    required: true
  },
  comment: {
    type: String,
    minlength: 5,
    maxlength: 500,
    required: true
  },
  insertDate: {
    type: Date,
    default: new Date()
  }
});

let Contact = mongoose.model("Contacts", contactSchema);

module.exports = {
  Contact
};

 

و در نهایت فایل اجرایی app.js با محتویات زیر رو به پروژه اضافه کنید :

const express = require("express");
const http = require("http");
const app = express();
const cors = require("cors");
const bodyParser = require("body-parser");
app.use(bodyParser.json());
app.use(cors());
const { Contact } = require("./contact");

app.post("/addContact", async (req, res) => {
  const contact = new Contact(req.body);
  contact
    .save()
    .then(() => {
      res.status(200).send("پیام جدید ثبت شد");
    })
    .catch((error) => {
      console.log(error);
      res.status(400).send("عملیات ثبت انجام نشد");
    });
});

app.post("/updatecontact", async (req, res) => {
  const id = req.query.id;
  await Contact.findByIdAndUpdate(id, req.body, (err, result) => {
    if (err) {
      res.status(400).send("عملیات ویرایش انجام نشد");
      return;
    }
    if (result === null) {
      return res.status(400).send("رکورد یافت نشد");
    }
    res.status(200).send("پیام ویرایش شد");
  });
});

app.get("/getcontacts", async (req, res) => {
  const contacts = await Contact.find();
  res.status(200).send(contacts);
});

app.get("/removecontact", async (req, res) => {
  const id = req.query.id;
  await Contact.findByIdAndRemove(id, (err, result) => {
    if (err) {
      return res.status(400).send("نظر یافت نشد");
    }
    if (result === null) {
      return res.status(400).send("رکورد یافت نشد");
    }
    res.status(200).send("رکورد با موفقیت حذف شد");
  });
});

const server = http.createServer(app);

server.listen(4000, () => {
  console.log("server running on port 4000");
});

 

بعد از ذخیره همه فایل ها برنامه رو با دستور node app.js اجرا کنید . 

 

ماژول cors :

 

Cross-Origin Resource Sharing): CORS) مکانیزمی است که از هدرهای HTTP  استفاده می کند تا به مرورگرها بگوید یک برنامه وب را در یک مبدأ اجرا کنند ، به اینصورت وقتی درخواستی از مبدا دیگری مثلا زیر دامنه یا پورت متفاوت ، درخواستی را ارسال کند سرور به صورت پیش فرض و برای حفظ امنیت  آن درخواست را رد میکند .

 

این ماژول برای این هست که به سرور بگیم جناب سرور عزیز شما  به درخواست های  ارسال شده از منابع دیگر نیز اجازه بده از سرور استفاده کنند . فراموش نکنید این ماژول تنظیماتی داره که میتونید مشخص کنید که دقیقا سرور به درخواست های کدام آدرس پاسخ بده در حالت پیش فرض با تنظیم این ماژول به روش زیر ، سرور به هر آدرسی اجازه دریافت اطالاعات رو میده .

app.use(cors());

 

 

کد های سمت کلاینت :

قرار هست که صفحه ای در ری اکت ایجاد کنیم که عملیات درج ، ویرایش ، مشاهده و حذف رو در اون صفحه بتونیم انجام بدیم . میتونیم نظر جدید ثبت کنیم یا با انتخاب نظرات ثبت شده اونها رو ویرایش یا حذف کنیم . با هر بار عملیات موفق مجددا داده ها از سرور خوانده و در جدول نمایش داده میشن .

پروژه ری اکت رو با دستور زیر ایجاد کنید :

npx create-react-app client-side

 

فولدر ایجاد رو به نام client-side رو باز کنید و ماژول های مورد نیازمون رو نصب میکنیم :

npm i axios bootstrap persian-date

 

به ترتیب axios برای ارتباط با سرور ، بوت استرپ برای دیزاین برنامه و پرشین دیت برای تبدیل و استفاده از تاریخ شمسی هستند .

 دستور زیر رو برای اضافه کردن کدهای استایل بوت استرپ به پروژه در فایل index.js قرار بدید . 

import "bootstrap/dist/css/bootstrap.min.css";

 

فایل Index.js باید حاوی اطلاعات زیر باشه :

import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import App from "./App";
import "bootstrap/dist/css/bootstrap.min.css";
import * as serviceWorker from "./serviceWorker";

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById("root")
);

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();

 

 

یک فایل با نام Service.js برای نوشتن کدهای ارتباط با سرور توسط ماژول axios ایجاد کنید و محتویات زیر رو به این فایل منتقل کنید  . همونطور که میبیند آدرس سرور با پورت 4000  بهمراه  نام مسیر متد ها برای ارسال درخواست به ماژول axios داده شده است .  
 

import http from "axios";
const serverUrl = "http://localhost:4000";

export function addContact(model) {
  return http.post(serverUrl + "/addContact", model);
}

export function editContact(model) {
  const id = model._id;
  delete model._id;
  return http.post(serverUrl + "/updatecontact?id=" + id, model);
}

export function removeContact(id) {
  return http.get(serverUrl + "/removecontact?id=" + id);
}

export function getContacts() {
  return http.get(serverUrl + "/getcontacts");
}

فرمت دستور http.post به اینصورت هست که در قسمت body اطلاعاتی رو که قصد داریم به صورت آبجکت یا آرایه به سرور ارسال کنیم ، قرار میدیم . و اطلاعاتی جزیی مثل id رو در url قرار میدیم که در سرور میتونیم از  طریق query دریافت کنیم .

http.post(url,body)

 

یک فایل با نام Contacts.jsx که قرار هست یک کامپوننت state less باشه و  اطلاعات موجود در  دیتا بیس رو به صورت یک جدول به صورت زیر نمایش بده ایجاد کنید. ما اطلاعات مورد نیازمون به صورت props به این کامپوننت ارسال میکنیم .

مشاهده اطلاعات جدول نظرات

 

 

import React from "react";
import persianDate from "persian-date";

const Contacts = (props) => {
  return (
    <table className="table">
      <thead>
        <tr>
          <th scope="col">#</th>
          <th scope="col">ایمیل</th>
          <th scope="col">عنوان</th>
          <th scope="col">نظر</th>
          <th scope="col">تاریخ درج</th>
          <th scope="col">انتخاب</th>
        </tr>
      </thead>
      <tbody>
        {props.contacts.map((contact, index) => {
          return (
            <tr key={index}>
              <th scope="row">{(index += 1)}</th>
              <td>{contact.email}</td>
              <td>{contact.title}</td>
              <td>{contact.comment}</td>
              <td>{new persianDate(new Date(contact.insertDate)).format()}</td>
              <td>
                <button
                  onClick={() => {
                    props.handleSelect(contact);
                  }}
                  className="btn btn-primary"
                >
                  انتخاب
                </button>
              </td>
            </tr>
          );
        })}
      </tbody>
    </table>
  );
};

export default Contacts;

 

یک فایل دیگه به نام EditContact.jsx  با محتویات زیر به پروژه اضافه کنید که قرار هست عملیات ویرایش و حذف توسط این کامپوننت انجام بشه :

import React, { Component } from "react";
import { editContact, removeContact } from "./Service";

class EditContact extends Component {
  state = {
    _id: "",
    email: "",
    title: "",
    comment: "",
  };

  componentDidMount() {
    const { _id, email, title, comment } = this.props;
    this.setState({ _id, email, title, comment });
  }

  componentWillReceiveProps(nextProps) {
    const { _id, email, title, comment } = nextProps;
    this.setState({ _id, email, title, comment });
  }

  handleSubmit = async (e) => {
    e.preventDefault();
    try {
      this.props.loading();
      if (
        this.state.email === "" ||
        this.state.title === "" ||
        this.state.comment === ""
      ) {
        this.props.unLoading(400, "اطلاعات کامل را وارد کنید");
        return;
      }
      await editContact(this.state);
      this.props.unLoading(200, "ویرایش با موفقیت انجام شد");
      this.props.getData();
    } catch (error) {
      if (error.response !== undefined)
        this.props.unLoading(error.response.status, error.response.data);
    }
  };

  handleRemove = async () => {
    if (window.confirm("ایا رکورد حذف شود ؟ ")) {
      try {
        this.props.loading();
        await removeContact(this.state._id);
        this.props.unLoading(200, "نظر با موفقیت حذف شد");
        this.props.getData();
      } catch (error) {
        if (error.response !== undefined)
          this.props.unLoading(error.response.status, error.response.data);
      }
    }
  };

  render() {
    return (
      <div>
        <form onSubmit={this.handleSubmit}>
          <div class="form-group">
            <label for="exampleInputEmail1">ایمیل</label>
            <input
              type="email"
              className="form-control"
              value={this.state.email}
              onChange={(e) => {
                this.setState({
                  email: e.target.value,
                });
              }}
            />
          </div>
          <div class="form-group">
            <label for="exampleInputEmail1">عنوان</label>
            <input
              type="text"
              className="form-control"
              value={this.state.title}
              onChange={(e) => {
                this.setState({
                  title: e.target.value,
                });
              }}
            />
          </div>
          <div class="form-group">
            <label for="exampleInputEmail1">نظر</label>
            <textarea
              type="text"
              rows={3}
              className="form-control"
              value={this.state.comment}
              onChange={(e) => {
                this.setState({
                  comment: e.target.value,
                });
              }}
            />
          </div>
          <button type="submit" className="btn btn-success m-1">
            ویرایش نظر
          </button>
          <button className="btn btn-danger m-1" onClick={this.handleRemove}>
            حذف نظر
          </button>
          <button className="btn btn-info m-1" onClick={this.props.newRecord}>
            انصراف
          </button>
        </form>
      </div>
    );
  }
}

export default EditContact;

 

شرح کدهای کامپوننت :

کدهایی که در بدنه متد componentDidMount قرار میگیرن در لحظه ای که کامپوننت ایجاد و آماده میشه ،  اجرا میشن یعنی فقط یکبار که مشابه دستور زیر در jquery  هست :

$(document).ready();

 

پس اگر دستوری رو اینجا وارد کنید همون بار اول اجرا میشه و تا پایان عمر کامپوننت بر قرار هست . یعنی اینکه اگر قرار باشه اطلاعاتی رو در props پاس بدید فقط بار اول دریافت میکنه و به تغییرات جدید props واکنشی نشون نمیده . خوب برای اینکه ما با زدن دکمه آبی انتخاب در جدول بتونیم هر بار اطلاعات هر نظر رو به این کامپوننت ارسال کنیم باید از  componentWillReceiveProps  استفاده کنیم . نحوه استفاده از سرویس های حذف و ویرایش  در کدها قابل مشاهده هست . شما میتوانید جهت دریافت اطلاعات بیشتر به مقاله متدهای چرخه حیات در ری اکت مراجعه نمائید .

و در نهایت فایل اصلی ما یعنی app.js باید حاوی  کدهای زیر باشه  :

import React, { Component } from "react";
import { getContacts } from "./Service";
import AddContact from "./AddContact";
import Contacts from "./Contacts";
import EditContact from "./EditContact";

class App extends Component {
  state = {
    alert: "",
    status: undefined,
    contacts: [],
    selected: null,
  };

  handleGetData = async () => {
    try {
      this.handleLoading();

      const { data } = await getContacts();
      this.setState({
        contacts: data,
        status: 200,
        alert: "دریافت اطلاعات با موفقیت انجام شد",
        selected: null,
      });
    } catch (error) {
      if (error.response !== undefined)
        this.handleUnloading(error.response.status, error.response.data);
    }
  };

  async componentDidMount() {
    await this.handleGetData();
  }

  handleSelect = (contact) => {
    this.setState({
      selected: contact,
    });
  };

  handleLoading = () => {
    this.setState({
      status: 0,
      alert: "",
    });
  };

  handleUnloading = (status, alert) => {
    this.setState({
      status,
      alert,
    });
  };

  handleNewRecord = () => {
    this.setState({
      selected: null,
    });
  };

  render() {
    return (
      <div className="container p-5">
        {this.state.status === 0 ? (
          <div className="spinner-border text-primary" role="status">
            <span className="sr-only">لطفا منتظر بمانید...</span>
          </div>
        ) : null}

        {this.state.status !== undefined ? (
          <div
            className={`alert alert-${
              this.state.status === 200 ? "success" : "danger"
            }`}
          >
            {this.state.alert}
          </div>
        ) : null}

        <div className="p-2">
          <button className="btn btn-info" onClick={this.handleGetData}>
            بروز رسانی اطلاعات
          </button>
        </div>

        <div className="p-1">
          {this.state.selected === null ? (
            <AddContact
              loading={this.handleLoading}
              unLoading={this.handleUnloading}
              getData={this.handleGetData}
            />
          ) : (
            <EditContact
              loading={this.handleLoading}
              unLoading={this.handleUnloading}
              getData={this.handleGetData}
              {...this.state.selected}
              newRecord={this.handleNewRecord}
            />
          )}
        </div>

        <div className="p-1">
          <Contacts
            handleSelect={this.handleSelect}
            contacts={this.state.contacts}
          />
        </div>

        <div className="p-1"></div>
      </div>
    );
  }
}

export default App;

 

به نحوه ارسال props در این کد دقت کنید :

 <EditContact
  loading={this.handleLoading}
  unLoading={this.handleUnloading}
  getData={this.handleGetData}
  {...this.state.selected}
  newRecord={this.handleNewRecord}
/>

ما به راحتی میتونیم متدهایی که در فایل app.js اجرا میشن رو با نام دلخواه به کامپوننت پاس بدیم  ، یعنی وقتی در کامپوننت فراخوانی میشن دستوری اجرا میشه که بدنه اون در فایل app هست . همینطور یک ابجکت با استفاده از spread operator ...  پاس داده شده که حاوی اطلاعات نظر انتخاب شده هست .

 

بسیار خوب کدهای ما آماده ست و با دستور npm start میتونید خروجی رو مشاهده کنید که باید به شکل زیر باشه :

در حالت ثبت نظر جدید به این شکل :

ثبت نظر جدید

 

و در حالت انتخاب نظر به این شکل :

حالت ویرایش یا حذف نظر

 

همونطور که مشاهده کردید در عملیات ما ، هرگز صفحه رفرش نمیشه و سرعت عملیات فوق العاده بالا ست که این از قدرت های ری اکت هست . بزودی برای شما عزیزان آموزشهای فوق رو به صورت ویدئویی در سایت قرار میدهم . امیدوارم این آموزش به شما در رفع مشکلات احتمالی کمک کرده باشه . اگر نظری دارید یا سوالی در این رابطه حتما در قسمت نظرات زیر همین پست با من در میون بگذارید .

 

فایل های هر دو پروژه برای شما جهت دانلود قرار داده شده . فقط دستور npm i برای اجرای هر دو رو فراموش نکنید . 

پروژه سمت سرور

پروژه سمت کلاینت 

نظرات :

در عرض چند دقیقه برای ایجاد حساب

کاربری خود اقدام کنید


اکنون حساب کاربری خود را ایجاد کنید!


ایجاد حساب کاربری

با ثبت نام در نیلوتک از آخرین بروز رسانی های آموزش ها و مقالات سایت مطلع شوید