如何使用React向Laravel应用程序发送一个POST请求

105 阅读7分钟

如何使用React向Laravel应用程序发送POST请求

也许你是一个后端工程师,想使用React库向你的网站加载数据,或者你想探索React与Laravel的使用。或者你对使用Laravel与React有其他兴趣,无论如何,你都来对了地方。

我们将学习如何使用React向Laravel应用程序发出POST请求并获取响应。

基本描述

  • React:这是一个JavaScript库,协助我们创建互动和动态的单页应用程序。
  • Axios:这是一个库,用于处理网络应用中对外部资源的HTTP请求。
  • Laravel:这是一个基于Model-View-Controller架构的PHP框架,帮助我们更快地创建Web后台应用程序。

前提条件

  • 对PHP和如何使用Laravel有基本的了解。
  • 对HTML和CSS有基本的了解。
  • 对JavaScript有基本的了解,以及如何在React上使用。
  • 在你的机器上安装有PHP, Composer, 和Laravel安装程序.

有了这些, 我们现在可以开始深入研究这个话题了。

我们将做什么

我们将从一个注册页面发送输入数据,并将数据发送到Laravel控制器,而控制器将返回JSON数据,并在警报中显示。

JSON, JavaScript Object Notation; 是一种Web应用程序之间的数据交换格式.

开始使用

我们通过在终端运行这个命令来创建我们的应用程序。

laravel new reactaxios

由于Laravel默认支持Vue.js,我们首先要用React.js替换Vue.js的支架。

php artisan preset react

创建控制器和路由

然后我们创建Laravel应用程序的控制器,接收POST请求。

php artisan make:controller AxiosReceiverController

打开控制器,添加以下代码。

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class AxiosReceiverController extends Controller
{
    public function ReceiveIt(Request $request){
        $validatedData = $request->validate([
            'firstname' => 'nullable',
            'lastname' => 'nullable',
            'email' => 'nullable',
            'phone' => 'nullable',
            'NatID' => 'nullable',
            'password' => 'nullable',
            'userLevel' => 'nullable'
        ]);

        return json_encode($validatedData);
    }
}

该控制器包含一个方法ReceiveIt() ,它接收一个请求,根据用户规则进行验证,然后将其存储在一个名为$validatedData 的数组中。然后,它将数组作为JSON对象返回,我们将在后面检索。

然后我们在routes/web.php文件中为控制器创建一个路由。

Route::post('sendrequest', 'App\Http\Controllers\AxiosReceiverController@ReceiveIt');

建立React和Frontend模块

我们添加我们的应用程序的依赖性。

npm install

为了处理我们的路由,我们将使用React Router,为所有的路由渲染一个单一的视图。如果你有很多路由,这一点尤其重要。对于我们的情况,它将只有一个路由。

我们将在routes/web中创建一个通配符路由,其中的视图文件app.blade.php将被用来渲染我们的React组件。用下面的代码替换rouse/web中的视图代码。

Route::view('/{path?}', 'app');

我们前往resources/views目录,创建app.blade.php文件并添加以下代码。

<!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <!-- CSRF Token -->
        <title>ReactAxios</title>
        <!-- Styles -->
        <link href="{{ asset('css/app.css') }}" rel="stylesheet">
    </head>
    <body>
        <div id="app"></div>

        <script src="{{ asset('js/app.js') }}"></script>
    </body>
    </html>

我们引用了一个CSS文件和一个JavaScript文件,其中包含React和其他依赖性。我们有一个id为"app" 的空div,我们的组件将在这里被呈现。

接下来,我们在resources/js/components中创建App组件,名称为App.jsx,并删除默认存在的Example.js

import React, { Component } from 'react'
import ReactDOM from 'react-dom'
import { BrowserRouter, Route, Switch } from 'react-router-dom'
import './App.css';

class App extends Component {
  render () {
    return (
      <BrowserRouter>
        <div>
          <Switch>
            
          </Switch>
        </div>
      </BrowserRouter>
    )
  }
}

ReactDOM.render(<App />, document.getElementById('app'))

我们将安装React路由器,因为我们正在使用它。

npm install react-router-dom

在继续安装的同时,直接打开resources/js/中app.js文件,用这个文件更新那里的代码。

    require('./bootstrap')
    require('./components/App')

注册页面

我们将在resources/js/components/目录下创建一个名为pages的文件夹,在这里我们将创建注册页面,将其命名为Register.jsx,并将其添加到该文件夹。在里面添加以下代码。

import React, { Component } from 'react';
import axios from "axios";
import wave from 'https://terrence-aluda.com/wave.png'
import bg from 'https://terrence-aluda.com/bg.svg'
import avatar from 'https://terrence-aluda.com/avatar.svg'

class Register extends Component {

    constructor(props){
        super(props);

        this.state = {
            firstname : '',
            lastname : '',
            email : '',
            phone : '',
            NatID : '',
            password : '',
            userLevel : 'Job Expert'
        }

        this.firstName = this.firstName.bind(this);
        this.lastName = this.lastName.bind(this);
        this.takePhone = this.takePhone.bind(this);
        this.takeEmail = this.takeEmail.bind(this);
        this.takeID = this.takeID.bind(this);
        this.takePassword = this.takePassword.bind(this);
        this.takeLevel = this.takeLevel.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
    }

    firstName(event){
        this.setState({firstname : event.target.value})
    }
    lastName(event){
        this.setState({lastname : event.target.value})
    }
    takePhone(event){
        this.setState({phone : event.target.value})
    }
    takeEmail(event){
        this.setState({email : event.target.value})
    }
    takeID(event){
        this.setState({ID : event.target.value})
    }
    takePassword(event){
        this.setState({password : event.target.value})
    }
    takeLevel(event){
        this.setState({userLevel : event.target.value})
    }

    handleSubmit(){
    
        const packets = {
            firstname:  this.state.firstname,
            lastname: this.state.lastname,
            email: this.state.email,
            phone: this.state.phone,
            NatID: this.state.ID,
            userLevel: this.state.userLevel,
            password: this.state.password
        };
        axios.post('/sendrequest', packets)
            .then(
                response => alert(JSON.stringify(response.data))
                
                )
            .catch(error => {
                console.log("ERROR:: ",error.response.data);
                
                });
    }

    render(){
        return (
<div>
            
            <img class="wave" src={wave} alt="img"/>
            <div class="container">
                <div class="img">
                    <img src={bg} alt="img"/>
                </div>
                <div class="login-content">
                    <form>
                        <img src={avatar} alt="img"/>
                        <h2 class="title">Register</h2>
                           <div class="input-div one">
                              <div class="i">
                                      <i class="fas fa-user"></i>
                              </div>
                              <div class="div">
                                      <h5></h5>
                                      <input type="text" placeholder="First Name" onChange={this.firstName} class="input"/>
                              </div>
                           </div>
            
                           <div class="input-div one">
                              <div class="i">
                                      <i class="fas fa-user"></i>
                              </div>
                              <div class="div">
                                      <h5></h5>
                                      <input type="text" placeholder="Last Name" onChange={this.lastName} class="input"/>
                              </div>
                           </div>
            
                           <div class="input-div pass">
                              <div class="i"> 
                                   <i class="fas fa-envelope-square"></i>
                              </div>
                              <div class="div">
                                   <h5></h5>
                                   <input type="email" placeholder="Email" onChange={this.takeEmail} class="input" />
                           </div>
                        </div>
            
                        <div class="input-div pass">
                              <div class="i"> 
                                   <i class=""></i>
                              </div>
                              <div class="div">
                              <select onChange={this.takeLevel} name="userLevel">
                                    <option value="">Choose level</option>                                 
                                    <option value="Job Expert">Job Expert</option>
                                    <option value="Client">Client</option>
                                </select>
                           </div>
                        </div>
            
                        <div class="input-div pass">
                              <div class="i"> 
                                   <i class="fas fa-id-card"></i>
                              </div>
                              <div class="div">
                                   <h5></h5>
                                   <input type="number" placeholder="National ID" onChange={this.takeID} class="input" />
                           </div>
                        </div>
            
                        <div class="input-div pass">
                              <div class="i"> 
                                   <i class="fas fa-phone"></i>
                              </div>
                              <div class="div">
                                   <h5></h5>
                                   <input type="number" placeholder="Phone Number" onChange={this.takePhone} class="input" />
                           </div>
                        </div>
            
                           <div class="input-div pass">
                              <div class="i"> 
                                   <i class="fas fa-lock"></i>
                              </div>
                              <div class="div">
                                   <h5></h5>
                                   <input type="password" placeholder="Password" onChange={this.takePassword} class="input" />
                           </div>
                        </div>
            
                        <div class="input-div pass">
                              <div class="i"> 
                                   <i class="fas fa-lock"></i>
                              </div>
                              <div class="div">
                                   <h5></h5>
                                   <input type="password" placeholder="Confirm Password" class="input" />
                           </div>
                        </div>
                        <input type="submit" class="btn" onClick={this.handleSubmit} value="Register"/>
                    </form>
                </div>
            </div>
                    
                </div>
        );
    }
}
export default Register;

解释

我们引用我们将在页面上使用的图片。

然后构造函数初始化状态值并绑定组件的函数。

后续的函数用于在用户输入后从其调用的输入中取值,然后适当地设置状态值。

当提交按钮被点击时,handleSubmit() 函数被调用。该函数包含一个名为packets 的对象,其属性来自state 对象。然后在Axios的post方法中作为请求传给我们创建的Laravel控制器路由。

在请求之后,我们检索结果,并使用JSON.stringify() 方法在警报中显示,该方法将返回的对象转换为一个字符串。如果在这个过程中出现了错误,在被 "捕获 "后会显示在控制台。

为页面添加样式并更新App.jsx文件

对于样式,你可以自定义并添加你自己的样式,但我们将使用什么来格式化我们的页面,是在下面的CSS代码中。

打开resources/js/components/App.css,添加这段代码。

@import url('https://fonts.googleapis.com/css2?family=Nunito:wght@200&family=Roboto:wght@100&display=swap');

:root{
  --nav-width: 68px;

  /* colors */
  --first-color: #00BFA6/*#472347D9*/;
  --first-color-light: #fff/*#AFA5D9*/;
  --white-color: #F7F6FB;

  /* === Font and Typography */
  --body-font: 'Nunito', sans-serif;
  --normal-font-size: 1rem;
  /* z-index */
  --z-fixed: 100;
}

body{
  font-family: Nunito, sans-serif;
  position: relative;
  /* margin: var(--header-height) 0 0 0; */
  margin: 0;
  padding: 0;
  font-family: var(--body-font);
  font-size: var(--normal-font-size);
  transition: .5s;
}

*, ::before, ::after{
  box-sizing: border-box;
}

body::-webkit-scrollbar{
  width: 8px;
}

body::-webkit-scrollbar-thumb{
  background-color: rgb(36, 36, 36);
}
body::-webkit-scrollbar-track{
  background-color: rgb(235, 236, 235);
}

.login-register{
  display: flex;
  justify-content: space-between;
}
.login-register a{
  margin-right: 6px;
}
a{
  text-decoration: none;
}

form {
  background: white;
  border: 1px solid #dedede;
  display: flex;
  flex-direction: column;
  justify-content: space-around;
  margin: 0 auto;
  max-width: 500px;
  padding: 30px 50px;
}
button{
  border: none;
  border-radius: 5px;
}


input,select {
  border: 1px solid #d9d9d9;
  border-radius: 4px;
  box-sizing: border-box;
  padding: 10px;
  width: 100%;
}

label {
  color: #3d3d3d;
  display: block;
  font-family: sans-serif;
  font-size: 14px;
  font-weight: 500;
  margin-bottom: 5px;
}

li{
  list-style: none;
  margin: 0 10px;
}


/**Login**/

.wave{
  position: fixed;
  bottom: 0;
  left: 0;
  height: 100%;
  z-index: -1;
}

.container{
    width: 100vw;
    height: 100vh;
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    grid-gap :7rem;
    padding: 0 2rem;
}

.img{
  display: flex;
  justify-content: flex-end;
  align-items: center;
}

.login-content{
  display: flex;
  justify-content: flex-start;
  align-items: center;
  text-align: center;
}

.img img{
  width: 500px;
}

form{
  width: 360px;
}

.login-content img{
    height: 100px;
}

.login-content h2{
  margin: 15px 0;
  color: #333;
  text-transform: uppercase;
  font-size: 2.9rem;
}

.login-content .input-div{
  position: relative;
    display: grid;
    grid-template-columns: 7% 93%;
    margin: 25px 0;
    padding: 5px 0;
    border-bottom: 2px solid #d9d9d9;
}

.login-content .input-div.one{
  margin-top: 0;
}

.i{
  color: #d9d9d9;
  display: flex;
  justify-content: center;
  align-items: center;
}

.i i{
  transition: .3s;
}

.input-div > div{
    position: relative;
  height: 45px;
}

.input-div > div > h5{
  position: absolute;
  left: 10px;
  top: 50%;
  transform: translateY(-50%);
  color: #999;
  font-size: 18px;
  transition: .3s;
}

.input-div:before, .input-div:after{
  content: '';
  position: absolute;
  bottom: -2px;
  width: 0%;
  height: 2px;
  background-color: #38d39f;
  transition: .4s;
}

.input-div:before{
  right: 50%;
}

.input-div:after{
  left: 50%;
}

.input-div.focus:before, .input-div.focus:after{
  width: 50%;
}

.input-div.focus > div > h5{
  top: -5px;
  font-size: 15px;
}

.input-div.focus > .i > i{
  color: #38d39f;
}

.input-div > div > input{
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  border: none;
  outline: none;
  background: none;
  padding: 0.5rem 0.7rem;
  font-size: 1.2rem;
  color: #555;
  font-family: 'poppins', sans-serif;
}

.input-div.pass{
  margin-bottom: 4px;
}

a{
  display: block;
  text-align: right;
  text-decoration: none;
  color: #999;
  font-size: 0.9rem;
  transition: .3s;
}

a:hover{
  color: #38d39f;
}

.btn{
  display: block;
  width: 100%;
  height: 50px;
  border-radius: 10px;
  outline: none;
  border: none;
  background-image: linear-gradient(to right, #32be8f, #38d39f, #32be8f);
  background-size: 200%;
  font-size: 1.2rem;
  color: #fff;
  font-family: 'Poppins', sans-serif;
  text-transform: uppercase;
  margin: 1rem 0;
  cursor: pointer;
  transition: .5s;
}
.btn:hover{
  background-position: right;
}


@media screen and (max-width: 1050px){
  .container{
    grid-gap: 5rem;
  }
}

@media screen and (max-width: 1000px){
  form{
    width: 290px;
  }

  .login-content h2{
        font-size: 2.4rem;
        margin: 8px 0;
  }

  .img img{
    width: 400px;
  }
}

@media screen and (max-width: 900px){
  .container{
    grid-template-columns: 1fr;
  }

  .img{
    display: none;
  }

  .wave{
    display: none;
  }

  .login-content{
    justify-content: center;
  }
}

/**fire**/
.fa-fire{
  color: rgb(255,102,102);
  font-size: 3.8rem;
}

footer{
  font-size: 1.5rem;
  padding: 0.8rem;
  text-align: center;
  background-color: rgb(20, 20, 20);
  color:#F7F6FB;
  }

.dash{
  background-color:#f2f4f6;
  min-width: 60vw;
  display: flex;
  justify-content: center;
  align-items: center;
}

.card-header{
  background-color: #32be8f;
  color: #fff;
}

.list-group-flush li:first-child{
  font-size: 1.8rem;
  color: blue;
  text-decoration: underline;
}

.list-group-flush li:nth-child(2){
  color: #6026ff;
  font-size: 1.1rem;
  font-weight: 500;
}

.list-group-flush{
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  align-items: center;
}

我们用这段代码更新App.jsx 文件,以显示路线。

import React, { Component } from 'react'
import ReactDOM from 'react-dom'
import { BrowserRouter, Route, Switch } from 'react-router-dom'
import './App.css';
import RegisterPage from './pages/Register';

class App extends Component {
  render () {
    return (
      <BrowserRouter>
        <div>
          <Switch>
            <Route exact path='/' component={RegisterPage} />     
          </Switch>
        </div>
      </BrowserRouter>
    )
  }
}

ReactDOM.render(<App />, document.getElementById('app'))

运行应用程序

在运行应用程序之前, 我们首先需要使用Laravel Mix来测试-编译反应,运行这个命令。

npm run dev

然后运行Laravel服务器:

php artisan serve

预期的输出。

First Screenshot

Second Screenshot

Third Screenshot

结论

在本教程中, 我们了解了如何使用Axios库来发送一个HTTP请求.一个POST请求,用于使我们的应用程序RESTful。我们看到了JSON在后端和前端之间传递信息的用途。我将在其他教程中谈论使用这些技术的其他HTTP方法。

这就是目前的全部内容。希望你已经深入了解了如何使用Axios从React向Laravel应用程序发出POST请求。