0303github搜索案例-react应用

news2024/11/25 13:38:26

文章目录

    • 1 前言
    • 2 静态组件
      • 2.1 静态页面和样式
      • 2.2 静态组件
    • 3 axios请求github接口
    • 4 优化案例
    • 结语

1 前言

学习了脚手架配置axios,我们通过访问github的接口来做个练习。实例效果如下所示:

在这里插入图片描述

搜索框输入github用户名关键字,点击搜索,列表展示对应的头像和用户名,点击跳转github主页。

基于我们访问github访问慢或者根本打不开的情况,我们通过nodejs,简单的写了个后端服务,代码1-1如下:

const express = require("express")
const axios = require("axios")
const app = express()


/*
  请求地址: http://localhost:3000/search/users?q=aa

  后台路由
    key: /search/users
    value: function () {}
*/
app.get("/search/users", function (req, res) {
  const {q} = req.query
  axios({
    url: 'https://api.github.com/search/users',
    params: {q}
  }).then(response => {
    res.json(response.data)
  })
})

app.get("/search/users2", function (req, res) {
  res.json({
    items: [
      {
        login: "yyx990803",
        html_url: "https://github.com/yyx990803",
        avatar_url:
          "https://avatars3.githubusercontent.com/u/499550?s=460&u=de41ec9325e8a92e281b96a1514a0fd1cd81ad4a&v=4",
        id: 1,
      },
      {
        login: "ruanyf",
        html_url: "https://github.com/ruanyf",
        avatar_url: "https://avatars2.githubusercontent.com/u/905434?s=460&v=4",
        id: 2,
      },
      {
        login: "yyx9908032",
        html_url: "https://github.com/yyx990803",
        avatar_url:
          "https://avatars3.githubusercontent.com/u/499550?s=460&u=de41ec9325e8a92e281b96a1514a0fd1cd81ad4a&v=4",
        id: 3,
      },
      {
        login: "ruanyf2",
        html_url: "https://github.com/ruanyf",
        avatar_url: "https://avatars2.githubusercontent.com/u/905434?s=460&v=4",
        id: 4,
      },
      {
        login: "yyx9908033",
        html_url: "https://github.com/yyx990803",
        avatar_url:
          "https://avatars3.githubusercontent.com/u/499550?s=460&u=de41ec9325e8a92e281b96a1514a0fd1cd81ad4a&v=4",
        id: 5,
      },
      {
        login: "ruanyf3",
        html_url: "https://github.com/ruanyf",
        avatar_url: "https://avatars2.githubusercontent.com/u/905434?s=460&v=4",
        id: 6,
      },
      {
        login: "yyx9908034",
        html_url: "https://github.com/yyx990803",
        avatar_url:
          "https://avatars3.githubusercontent.com/u/499550?s=460&u=de41ec9325e8a92e281b96a1514a0fd1cd81ad4a&v=4",
        id: 7,
      },
      {
        login: "ruanyf4",
        html_url: "https://github.com/ruanyf",
        avatar_url: "https://avatars2.githubusercontent.com/u/905434?s=460&v=4",
        id: 8,
      },
      {
        login: "yyx9908035",
        html_url: "https://github.com/yyx990803",
        avatar_url:
          "https://avatars3.githubusercontent.com/u/499550?s=460&u=de41ec9325e8a92e281b96a1514a0fd1cd81ad4a&v=4",
        id: 9,
      },
    ],
  });
});



app.listen(5000, "localhost", (err) => {
  if (!err){
  	console.log("服务器启动成功")
  	console.log("请求github真实数据请访问:http://localhost:5000/search/users")
  	console.log("请求本地模拟数据请访问:http://localhost:5000/search/users2")
  } 
  else console.log(err);
})

  • 如果正常访问github接口https://api.github.com/search/users网络延迟高或者打不开,可以切换为我们模拟的接口。

2 静态组件

2.1 静态页面和样式

页面简单的包含搜索组件和列表展示组件,静态html和css代码如下2-1所示:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <link rel="stylesheet" href="./bootstrap.css">
  <link rel="stylesheet" href="./index.css">
</head>
<body>
<div id="app">
  <div class="container">
    <section class="jumbotron">
      <h3 class="jumbotron-heading">Search Github Users</h3>
      <div>
        <input type="text" placeholder="enter the name you search"/>&nbsp;<button>Search</button>
      </div>
    </section>
    <div class="row">
      <div class="card">
        <a href="https://github.com/reactjs" target="_blank">
          <img src="https://avatars.githubusercontent.com/u/6412038?v=3" style='width: 100px'/>
        </a>
        <p class="card-text">reactjs</p>
      </div>
      <div class="card">
        <a href="https://github.com/reactjs" target="_blank">
          <img src="https://avatars.githubusercontent.com/u/6412038?v=3" style='width: 100px'/>
        </a>
        <p class="card-text">reactjs</p>
      </div>
      <div class="card">
        <a href="https://github.com/reactjs" target="_blank">
          <img src="https://avatars.githubusercontent.com/u/6412038?v=3" style='width: 100px'/>
        </a>
        <p class="card-text">reactjs</p>
      </div>
      <div class="card">
        <a href="https://github.com/reactjs" target="_blank">
          <img src="https://avatars.githubusercontent.com/u/6412038?v=3" style='width: 100px'/>
        </a>
        <p class="card-text">reactjs</p>
      </div>
      <div class="card">
        <a href="https://github.com/reactjs" target="_blank">
          <img src="https://avatars.githubusercontent.com/u/6412038?v=3" style='width: 100px'/>
        </a>
        <p class="card-text">reactjs</p>
      </div>
    </div>
  </div>
</div>
</body>
</html>

样式使用bootstrap的样式,我们直接放入public\css下面,在主页index.html引入

我们自定义的样式,自定义样式代码如下:

.album {
  min-height: 50rem; /* Can be removed; just added for demo purposes */
  padding-top: 3rem;
  padding-bottom: 3rem;
  background-color: #f7f7f7;
}

.card {
  float: left;
  width: 33.333%;
  padding: .75rem;
  margin-bottom: 2rem;
  border: 1px solid #efefef;
  text-align: center;
}

.card > img {
  margin-bottom: .75rem;
  border-radius: 100px;
}

.card-text {
  font-size: 85%;
}

2.2 静态组件

使用脚手架创建项目后,去除不需要的文件,其中public/css 下放置bootstrap.css,在index.html中引入,代码如下所示:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
  <link rel="stylesheet" href="./css/bootstrap.css">
  <title>React 脚手架</title>
</head>
<body>
  <div id="root"></div>
</body>
</html>

src目录下创建2个组件:

  • Search组件:对应页面搜索部分;
  • List组件:对应列表展示部分。

App.jsx代码2.2-2如下所示:

import React, { Component } from 'react'
import './app.css'
import Search from './component/Search'
import List from './component/List'


export default class App
  extends Component {

  render() {

    // const { githubUsers } = this.state

    return (
      <div>
        <div className="container">
          <Search />
          <List />
        </div>
      </div>
    )
  }
}

Seach组件初始状态代码2.2-3如下所示:

import React, { Component } from 'react'

export default class Search extends Component {

  render() {

    return (
      <section className="jumbotron">
        <h3 className="jumbotron-heading">搜索github用户</h3>
        <div>
          <input type="text" placeholder="输入用户名" />&nbsp;
          <button>搜索</button>
        </div>
      </section>
    )
  }
}

List组件初始状态代码2.2-4如下所示:

import React, { Component } from 'react'

export default class List extends Component {
  render() {
    const { isFirst, isLoading, githubUsers, err } = this.props
    return (
      <div className="row">
        <div className="card" >
          <a target="_blank">
            <img alt='avatar' src="https://avatars.githubusercontent.com/u/6412038?v=3" style={{ width: '100px' }} />
          </a>
          <p className="card-text">xxx</p>
        </div>
        <div className="card" >
          <a target="_blank">
            <img alt='avatar' src="https://avatars.githubusercontent.com/u/6412038?v=3" style={{ width: '100px' }} />
          </a>
          <p className="card-text">xxx</p>
        </div>
        <div className="card" >
          <a target="_blank">
            <img alt='avatar' src="https://avatars.githubusercontent.com/u/6412038?v=3" style={{ width: '100px' }} />
          </a>
          <p className="card-text">xxx</p>
        </div>
      </div>
    )
  }
}

  • 修改类名和样式以后不在提示

3 axios请求github接口

我们自定义样式,都是些的List组件的样式,我们直接把样式放置在List对应的组件处,List组件引入样式。

流程梳理:search请求github接口,返回数据;把数据传递给List组件用于展示。

Search组件和List组件属于兄弟组件,传值目前我们需要通过其父组件App来传递。

第一步:App组件初始化用户数组状态

  state = { 
    githubUsers: [], // 初始化状态,github用户
  } 

第二步:Search请求后端接口,后端请求github接口返回数据;数据返回后,把数据传递给App。代码3-2如下所示:

// Search组件
import React, { Component } from 'react'
import axios from 'axios'

export default class Search extends Component {

  search = () => {
    // 获取用户输入
    const {keyElement: {value: keyword}} = this
    // 发起网络请求
    axios.get(`/api1/search/users?q=${keyword}`).then(
      resp => {
        // console.log('请求成功',resp.data);
        const data = resp.data.items.map(item => {
          return {id: item.id, avatar: item.avatar_url, homePage: item.html_url, username: item.login}
        })
        this.props.updateAppState(data)
      },
      error => {
        // console.log('请求失败', err);
      }
    )
  }
  
  render() {

    return (
      <section className="jumbotron">
        <h3 className="jumbotron-heading">搜索github用户</h3>
        <div>
          <input ref={c => this.keyElement = c} type="text" placeholder="输入用户名" />&nbsp;
          <button onClick={this.search}>搜索</button>
        </div>
      </section>
    )
  }
}

// App组件
  /**
   * 更新用户状态数据
   * @param {object} githubUsers 
   */
  updateAppState = (githubUsers) => {
    // 更新用户
    this.setState({githubUsers})
  }
<Search updateAppState={this.updateAppState}/>

第三步:App把数据传递给List,展示数据,代码3-3如下所示

// App 组件
<List {...this.state}/>
// List 组件
render() {
    const { isFirst, isLoading, githubUsers, err } = this.props
    return (
      <div className="row">
        {
           githubUsers.map(item => {
                return (
                  <div className="card" key={item.id}>
                    <a href={item.homePage} target="_blank" rel="noreferrer">
                      <img alt='avatar' src={item.avatar} style={{ width: '100px' }} />
                    </a>
                    <p className="card-text">{item.username}</p>
                  </div>
                )
              })
           }
      </div>
    )
  }

第四步:配置代理,setupProxy.js代码3-4如下

const { createProxyMiddleware } = require("http-proxy-middleware")

module.exports = function (app) {
  app.use(
    createProxyMiddleware("/api1",{
      target: "http://localhost:5000", //配置转发目标地址(能返回数据的服务器地址)
      changeOrigin: true, //控制服务器接收到的请求头中host字段的值
      pathRewrite: { "^/api1": "" }, 
    })
  )
}

4 优化案例

虽然点击搜索能实现效果了但是,存在一些问题:

  • 列表初始需要展示欢迎或者提示信息;
  • 当开始请求后,数据未返回前,展示加载信息;
  • 数据请求成功后,展示用户信息;数据请求失败,展示错误信息。

这时候我们需要拓展App中的状态数据如下所示:

  state = { 
    githubUsers: [], // 初始化状态,github用户
    isFirst: true, // 是否第一次打开页面
    isLoadign: false, // 数据是否加载中
    err: '', // 存储相关的错误信息
  } 

Search组件相应的做出调整如下:

  search = () => {
    // 获取用户输入
    const {keyelement: {value: keyword}} = this
    // console.log(keyword);
    // 发送请求前通知App更新状态
    this.props.updateAppState({isFirst: false, isLoading: true})
    // 发起网络请求
    axios.get(`/api1/search/users?q=${keyword}`).then(
      resp => {
        // console.log('请求成功',resp.data);
        const data = resp.data.items.map(item => {
          return {id: item.id, avatar: item.avatar_url, homePage: item.html_url, username: item.login}
        })
        this.props.updateAppState({isLoading: false, githubUsers: data})
      },
      error => {
        // console.log('请求失败', err);
        this.props.updateAppState({isLoading: false, err: error.message})
      }
    )
  }

List组件展示根据数据,调整展示如下:

render() {
    const { isFirst, isLoading, githubUsers, err } = this.props
    return (
      <div className="row">
        {
          isFirst ? <h2>欢迎使用,输入github用户名,点击搜索</h2> :
            isLoading ? <h2>Loading......</h2> :
              err ? <h2 style={{color: 'red'}}>{err}</h2> :
                githubUsers.map(item => {
                  return (
                    <div className="card" key={item.id}>
                      <a href={item.homePage} target="_blank" rel="noreferrer">
                        <img alt='avatar' src={item.avatar} style={{ width: '100px' }} />
                      </a>
                      <p className="card-text">{item.username}</p>
                    </div>
                  )
                })
        }
      </div>
    )
  }
  
  

关于脚手架设置代理请求真实网络数据小案例,讲解完毕。我们之前兄弟之间传递数据非常的麻烦,下面我们将要学习消息发布和订阅来解决这个问题。

结语

❓QQ:806797785

⭐️源代码仓库地址:https://github.com/gaogzhen/react-staging.git

参考:

[1]React视频教程[CP/OL].2020-12-15.p65-66.

[2]React官网[CP/OL].

[2]ChatGPT[CP/OL].

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/425916.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AD633JRZ-ASEMI代理ADI亚德诺AD633JRZ车规级芯片

编辑-Z AD633JRZ芯片参数&#xff1a; 型号&#xff1a;AD633JRZ 总误差&#xff1a;1% 标度电压错误&#xff1a;0.25% 电源干扰&#xff1a;0.01% 输出偏移电压&#xff1a;5mV 小信号带宽&#xff1a;1MHz 斜率&#xff1a;20V/s 沉降时间达到1%&#xff1a;2s 宽…

在 Rocky linux 8.7 使用 Kubespray v2.21.0 离线部署 kubernetes v1.24.0 集群

文章目录前言创建7台虚拟机要求配置代理下载介质介质初始化安装工具包配置互信编写 inventory.ini创建 offline.ymlt他、部署 offline repo部署 kubespray报错2报错3报错报错&#xff1a;container-engine/containerd : containerd &#xff5c; Create registry directories分…

5.Dockerfile

1.什么是Dockerfile Dockerfile其实就是一个文本文件&#xff0c;由一系列命令和参数构成&#xff0c;Docker可以读取Dockerfile文件并根据Dockerfile文件的描述来构建镜像。 1、对于开发人员&#xff1a;可以为开发团队提供一个完全一致的开发环境&#xff1b; 2、对于测试人…

Servlet API

目录 1.HttpServlet 1.doGet 2.doPost 2.HttpServletRequest 2.1方法 2.2打印请求信息 2.3获取GET请求的参数 2.4post请求body格式 1.x-www-form-urlencoded 2.json 3.HttpServletResponse 3.1方法 3.2设置状态码 3.3自动刷新 3.4构造重定向的响应 1.HttpServlet 方法…

VMware Workstation Pro17安装并导入旧虚拟机系统

VMware Workstation Pro17 VMware是一个虚拟机软件&#xff0c;可以用来虚拟化各种系统&#xff0c;便于进行开发和其他相关工作 VMware Workstation Pro17支持window11版本&#xff0c;如果vm版本太低了升级window的时候会提示卸载旧版本的 下载VMware Workstation Pro17 h…

网格贪心搜索逼近最优组合解

如有错误&#xff0c;感谢不吝赐教、交流 文章目录背景描述实现方法一、寻找两组合的最优二、基于两组合的最优结果寻找四组合最优三、基于四组合的最优结果寻找八组合最优四、基于八组合的最优结果寻找十六组合最优总结适用场景背景描述 假如list [0, 1, 2, 3, 4, 5, 6, 7, …

2023年第三届智能机器人与系统国际会议(ISoIRS 2023) | IEEE-CPS独立出版

2023年第三届智能机器人与系统国际会议(ISoIRS 2023) | IEEE-CPS独立出版 会议简介 Brief Introduction 2023年第三届智能机器人与系统国际会议(ISoIRS 2023) 会议时间&#xff1a;2023年5月26日-28日 召开地点&#xff1a;中国长沙 大会官网&#xff1a;www.isoirs.org ISoIRS…

软件测试别再被“薪资陷阱”困扰了,这份攻略带你轻松查薪资

大家好&#xff0c;我是锦都不二。 测试岗面试 当HR问你期望薪资是多少时&#xff0c; 如果你回答: 10K 恭喜&#xff0c;你已经被HR成功套路&#xff0c; 拿到offer时你会在心里这么嘀咕&#xff1a;我要是当时报价15k该多好。 所以如何知道自己在这个市场上的价值&#xff0c…

95-拥塞控制

拥塞控制1.什么是拥塞控制2.拥塞控制的方法(1)慢启动和拥塞避免(2)快速重传和快速恢复1.什么是拥塞控制 在计算机网络中的链路容量&#xff08;即带宽&#xff09;、交换结点中的缓存和处理机等&#xff0c;都是网络的资源。在某段时间&#xff0c;若对网络中某一资源的需求超…

excel在文本的固定位置插入字符、进行日期和时间的合并

1.excel在文本的固定位置插入字符 如上图&#xff0c;现在想要将其转化为日期格式&#xff08;比如2017/1/1&#xff09;&#xff0c;但是当设置单元格格式为日期时却显示出很多&#xff03;。我们可以通过在20170101中添加两个斜杠“/”来将其转化为2017/1/1。可以用replace函…

基于SSM的二手车交易平台小程序

选题背景 互联网是人类的基本需求&#xff0c;特别是在现代社会&#xff0c;个人压力增大&#xff0c;社会运作节奏高&#xff0c;随着互联网的快速发展&#xff0c;用户的需求也越来越高&#xff0c;用户也将越来越多依靠互联网而不是自己获取信息&#xff0c;使得各种软件程…

【逗老师的无线电】BM的AirSecurity功能使用以防止他人使用你的DMRID

众所周知&#xff0c;在使用DMR热点和中继的时候&#xff0c;如果别人的手台上配置了你的ID进行恶意呼叫&#xff0c;或者伪装你的身份进行通联&#xff0c;之前是没有办法防范的。 目前&#xff0c;BM更新了AirSecurity功能&#xff0c;通过在呼叫前预先单呼一个作为密码的号码…

计算机组成原理——第二章数据的表示和运算(上)

提示&#xff1a;日出有盼&#xff0c;落日有念&#xff0c;心有所期&#xff0c;忙而不茫 文章目录前言2.1.1 进位计数制2.1.2 BCD码2.1.3 无符号整数的表示和运算2.1.4 带符号整数的表示和运算(原反补)2.1.5原反补码的特性对比2.1.6 移码2.1.7 定点小数前言 这里主要是根据王…

vue3 history模式配置及nginx服务器配置

vue的路由方式有hash模式和history模式&#xff0c;history模式路由看起来有好些&#xff0c;路由路径里没有#号&#xff0c;而hash模式默认是有#号的。 vue3开始默认新建的项目都是history模式&#xff0c;不过history模式打包后想要使用正常访问的话&#xff0c;需要后端服务…

BIO/NIO/Netty网络通信编程

文章目录1 BIO (BLOCK IO)2. NIO (new IO)2.1 NIO-Buffer缓冲区2.2 NIO-Buffer分散读-集中写2.3 NIO-Buffer粘包半包2.4 NIO-Channel2.4.1 files相关操作2.4.2 channel网络通信2.4.3 处理消息边界2.4.4 buffer大小分配2.4.5 处理大量写事件2.5 selector-Epoll2.6 IO模型2.7 零拷…

懒人必备!Python代码帮你自动发送会议纪要,让你有更多时间做更重要的事情

目录 痛点&#xff1a; 应用场景&#xff1a; 源代码&#xff1a; 代码说明&#xff1a; 效果如下所示&#xff1a; 痛点&#xff1a; 在传统的工作中&#xff0c;发送会议纪要是一个比较繁琐的任务&#xff0c;需要手动输入邮件内容、收件人、抄送人等信息&#xff0c;每…

代码随想录算法训练营第五十六天 | 583. 两个字符串的删除操作、72. 编辑距离、编辑距离总结

583. 两个字符串的删除操作 动规五部曲 1、确定dp数组&#xff08;dp table&#xff09;以及下标的含义 dp[i][j]&#xff1a;以i-1为结尾的字符串word1&#xff0c;和以j-1位结尾的字符串word2&#xff0c;想要达到相等&#xff0c;所需要删除元素的最少次数。 2、确定递推…

基于matlab使用Swerling目标模型来描述雷达横截面的波动

一、前言该示例说明了如何使用Swerling目标模型来描述雷达横截面的波动。该场景由旋转单基地雷达和具有Swerling 2模型描述的雷达横截面的目标组成。在此示例中&#xff0c;雷达和目标是静止的。二、斯威林 1 与斯威林 2 模型在Swerling 1和Swerling 2目标模型中&#xff0c;总…

Spring项目中如何接入Open AI?

前言 最近随着ChatGPT的爆火&#xff0c;很多人都坐不住了&#xff0c;OpenAI API 允许开发人员访问该模型并在其自己的应用程序中使用。那么它能给我们我们Java开发带来那些好处呢&#xff1f;又该怎么接入Open AI呢&#xff1f; 在开始之前&#xff0c;我们需要在 OpenAI 网…

安全沙箱技术小科普

安全沙箱技术是一种用于保护用户隐私和系统安全的机制&#xff0c;它可以将应用程序限制在一个封闭的运行环境中&#xff0c;防止其对系统和其他应用程序造成潜在的威胁。安全沙箱技术广泛应用于计算机安全领域&#xff0c;如防病毒软件、浏览器、操作系统等&#xff0c;以提高…