ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

nextjs代理转发fetch请求封装

2022-01-01 16:06:40  阅读:351  来源: 互联网

标签:const res api nextjs import 封装 let data fetch


demo 请狠狠的戳这里  https://download.lllomh.com/cliect/#/product/G909746950517113

 

一.配置代理

使用 create-next-app 创建的 Next.js 项目配置接口跨域代理转发需要用到 custom server 功能。
先安装好 express 和 http-proxy-middleware

yarn add express http-proxy-middleware

在项目根目录下新建 server.js 文件,写入以下代码

const express = require('express')
const next = require('next')
const createProxyMiddleware = require('http-proxy-middleware').createProxyMiddleware ;

const baseUrl='http://localhost:8000'

const devProxy = {
    '/api': {
        target: baseUrl, // 端口自己配置合适的
        pathRewrite: {
            '^/api': '/'
        },
        changeOrigin: true
    }
}

const port = parseInt(process.env.PORT, 10) || 8087
const dev = process.env.NODE_ENV !== 'production'
const app = next({
    dev
})
const handle = app.getRequestHandler()

app.prepare()
    .then(() => {
        const server = express()

        if (dev && devProxy) {
            Object.keys(devProxy).forEach((context)=> {
                server.use(createProxyMiddleware(context, devProxy[context]))
            })
        }

        server.all('*', (req, res) => {
            handle(req, res)
        })

        server.listen(port, err => {
            if (err) {
                throw err
            }
            console.log(`> Ready on http://localhost:${port}`)
        })
    })
    .catch(err => {
        console.log('An error occurred, unable to start the server')
        console.log(err)
    })

相应地修改 package.json

npm install cross-env  ---save

  "scripts": {
    "dev": "set PORT=8087 && node server.js",
    "build": "next build",
    "start": "cross-env NODE_ENV=production set PORT=8087 && node server.js",
    "lint": "next lint"
  },

如下,所有接口以 /api 开头即可。

const { data } = await axios.post('/api/users/', options)

 然后, 如果就这么写,在axios 是没事 ,但在fetch却是会报错Next.js - Error: only absolute urls are supported的,.

二.fecth封装带拦截携带cookie 跟 token

1,定义

根目录新建文件 /serve/index.js

import getConfig from 'next/config'
import QS from 'qs'
import {Toast} from 'antd-mobile';
const {publicRuntimeConfig} = getConfig()
let baseUrl = 'http://localhost:8087/api/'

// if (typeof window == 'undefined') {
//      baseUrl = publicRuntimeConfig.baseUrl
// }

export function  $fetch(method, url, body) {
    method = method.toUpperCase();
    if (method === 'GET') {
        // fetch的GET不允许有body,参数只能放在url中
        body = undefined;
    } else {
        body = body && QS.stringify(body);
    }
    console.log(baseUrl + url)
    return fetch(baseUrl + url, {
      method,
      headers: {
          'Content-Type': 'application/x-www-form-urlencoded',
          'Access-Control-Allow-credentials': 'true', // 每次携带cookie 必须加,不然不会携带
          'Authorization': 'token' // 从localStorageStorage中获取access token
      },
      body,
  },{credentials: 'include'}).then((res) => res.json()).then((data) => {
      if (data.code == '00001') { //token失效

      } else if (data.data ? data.data.token : "") { // 判断token是否存在,如果存在说明需要更新token
          // app.$cookies.set('USERINFO',JSON.stringify(res.data.data))
      } else if (data.code != '00000') {
          Toast.info(data.msg, 1);//后端错误弹出
      }
      return data
  })

}


2,调用

1.1 api定义 

/pages/api/index.js


let $api = "/api/"; //dev
if (process.env.NODE_ENV === "production") {
    // 为线上环境修改配置...
    //Modify the configuration for the online environment
        $api="http://localhost:8080/"  //线上
}

export const P_ZONLIST= 'api/index.php?route=address/zonelist';//地区列表

1.2 执行

/pages/login.js

import React from 'react';
import Link from 'next/link'
import { Cookie, withCookie } from 'next-cookie'
import { List, InputItem, Toast } from 'antd-mobile';
import { createForm } from 'rc-form';
import Router, { withRouter } from 'next/router'
import ButtonMaterial from '@material-ui/core/Button';
import LeftNav from '../../components/LeftNav'
import {$fetch} from '../../serve'
import {P_ZONLIST,P_LOGIN} from '../api'  // api/index.js


class Login extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            data:[],
            datas:[],
            pause:false,
            end:false,
            username:'',
            password:'',
            hasErrorUser:false,
            ispaly:true,
            type: 'money',
        }
    }


    async componentDidMount() {

        // let param={
        //     reqName:'Home'
        // }
        // let result = await $fetch('post',P_ZONLIST,{
        //     param
        // })
        // let res = await result.json(); //必须通过此方法才可返回数据
        // // console.log(res.data[0])
        // this.setState({datas:res.data})

    }

    one rrorClickUser = () => {
        if (this.state.hasErrorUser) {
            Toast.info('Please enter 11 digits');
        }
    }

    handleClick = () => {
        this.inputRef.focus();
    }

    onChangeUsername = (value) => {
        if (value.replace(/\s/g, '').length < 11) {
            this.setState({
                hasErrorUser: true,
            });
        } else {
            this.setState({
                hasErrorUser: false,
            });
        }
        this.setState({
            username:value,
        },()=>{
            console.log(this.state.username,'usernameusernameusernameusername')
        });
    }

    onChangePassword = (value) => {
        if (value.replace(/\s/g, '').length < 11) {
            this.setState({
                hasError: true,
            });
        } else {
            this.setState({
                hasError: false,
            });
        }
        this.setState({
            password:value,
        },()=>{
            console.log(this.state.password,'valuevaluevalue')
        });
    }

     handleClickSubmit= async ()=>{
         const { cookie } = this.props
        let param={
            reqName:'P_LOGIN',
            email:this.state.username,
            password:this.state.password,
        }
        let result = await $fetch('post',P_LOGIN,param)
        // let res = await result; //必须通过此方法才可返回数据
         if(result.code='00000'){
             cookie.set('USER', result.data)
         }
        console.log(result,'resultresult')
        // this.setState({datas:res.data})
        //  Router.push({pathname:'/user'})
    }

    render() {
        const { getFieldProps } = this.props.form;
        const { cookie } = this.props
        return <div className="container">
            <LeftNav/>
            {console.log(this.props.data)}
            Login {this.props.data[0]?this.props.data[0].zone_name:''}
            <List renderHeader={() => 'Customize to focus'}>
                <InputItem
                    {...getFieldProps('autofocus')}
                    clear
                    error={this.state.hasErrorUser}
                    one rrorClick={this.onErrorClickUser}
                    onChange={this.onChangeUsername}
                    value={this.state.username}
                    placeholder="auto focus"
                    ref={el => this.autoFocusInst = el}
                >用户名</InputItem>
                <InputItem
                    {...getFieldProps('focus')}
                    clear
                    type={`password`}
                    onChange={this.onChangePassword}
                    value={this.state.password}
                    placeholder="click the button below to focus"
                    ref={el => this.inputRef = el}
                >密码</InputItem>
                <List.Item>
                    <div
                        style={{ width: '100%', color: '#108ee9', textAlign: 'center' }}
                        onClick={this.handleClickSubmit}
                    >
                       login
                    </div>
                </List.Item>
            </List>
        </div>
    }
}


// Home.constructor=(props)=>{
//     // super(props);
//     this.state = {date: new Date()};
// }


// Home.getInitialProps = async (ctx) => {
//     let datas={
//         reqName:'Home'
//     }
//     let result = await $fetch('post','/api/launch/home',{
//         datas
//     })
//
//     let res = await result.json(); //必须通过此方法才可返回数据
//     const data = res.data
//     return {
//         stars: data,
//         props: {
//             data //props值传导render函数中
//         }
//     }
// }
//
// Home.componentDidMount=async ()=>{
//     console.log(this.state.date)
// }

export async function getServerSideProps() {
    let param={
        reqName:'Home'
    }
    let result = await $fetch('post',P_ZONLIST,{
        param
    })

    let res = await result; //必须通过此方法才可返回数据
    // const data = res.data
    console.log(res)
    return {
        props:{data:res.data}
    }
}

 Login = createForm()(Login);
export default withCookie(Login)

效果  ssr渲染 数据  携带 token 跟cookie

标签:const,res,api,nextjs,import,封装,let,data,fetch
来源: https://blog.csdn.net/lllomh/article/details/120184445

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有