React - github搜索小案例

案例最终效果如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

可将页面拆成三个组件
在这里插入图片描述
目录如下
在这里插入图片描述

1.思路

  • 初始化状态
  • 用户点击search按钮后,根据input中的value值获取内容并更新到状态中
  • 发送网络请求,将value拼接得到response并更新状态
  • 请求的数据进行展示
  • 完善用户体验,添加一些状态,第一次输入时,正在加载时,响应错误时

2.主要逻辑代码

脚手架配置代理,解决跨域问题,setupProxy.js

const proxy = require('http-proxy-middleware')

module.exports = function (app) {
    app.use(
        proxy('/api1',{ // 遇见/api1前缀的请求,就会触发该代理配置
            target: 'http://localhost:5000', // 请求转发给谁
            changeOrigin: true, // 控制服务器收到的请求头中Host的值
            pathRewrite: {'^/api1':''} // 重写请求路径(必须)
        })
    )
}

App.js

// 创建“外壳”组件App
import React,{Component} from 'react'

import Search from "./components/Search/index";
import List from "./components/List/index";

import "./App.css"

class App extends Component{
    // 初始化状态
    state = {
        users: [], //users初始值为数组
        isFirst: true, //是否为第一次打开页面
        isLoading: false, //是否处于加载中
        err: '', //存储请求的相关信息
    }
    // 更新App的state
    updateAppState = (stateObj) => {
        // 因为本身就是一个对象,所以不用写{}
        this.setState(stateObj)
    }
    render() {
        return (
            <div className="total">
                <Search updateAppState={this.updateAppState}/>
                <List {...this.state}/>
            </div>
        )
    }
}
export default App

Search.js

import React,{Component} from "react"
import axios from "axios";

import "./index.css"

export default class Search extends Component {
    // 点击搜索按钮搜索
    search = () => {
        // 拿到输入框的数据
        const {inputElement} = this
        console.log(inputElement.value)
        // 发送请求前通知App更新状态
        this.props.updateAppState({isFirst:false,isLoading:true})
        // 发送网络请求
        axios.get(`http://localhost:3000/api1//search/users?q=${inputElement.value}`).then(
            response => {
                console.log(response.data.items)
                // 请求成功后通知App更新状态
                this.props.updateAppState({isLoading: false, users: response.data.items})
            },
            error => {
                // 请求失败后通知App更新状态
                this.props.updateAppState({isLoading:false,err:error.message})
            }
        )
    }
    render() {
        return (
            <div className="search">
                <div className="container">
                    <h3>Search Github Users</h3>
                    <input type="text" ref={c => this.inputElement = c} placeholder="enter the name you search"/>
                    &nbsp;<button onClick={this.search}>Search</button>
                </div>

            </div>
        )
    }
}

List.js

import React,{Component} from "react"
import Item from "../Item/index";

import "./index.css"

export default class List extends Component {
    render() {
        const {users,isFirst,isLoading,err} = this.props
        return (
            <ul className="totalPhoto">
                {
                    // 必须写表达式,所以不能写if语句
                    isFirst? <h2>欢迎使用,输入关键字,随后点击搜索</h2>: isLoading? <h2>Loading...</h2>:
                        err? <h2>err</h2>:
                            users.map((user)=> {
                                return <Item key={user.id} user={user} {...user}/>
                            })
                }
            </ul>
        )
    }
}

Item.js

import React,{Component} from "react"

import "./index.css"

export default class Item extends Component {
    render() {
        const {user} = this.props
        return (
            <div className="photo">
                <section>
                    <a href={user.html_url} target="_blank">
                        <img src={user.avatar_url} alt=""/>
                    </a>
                    <p className="text">{user.login}</p>
                </section>
            </div>
        )
    }
}

3.知识点和注意点

  • 发送网络请求的那一套模板
  • 简单了解并解决跨域问题
  • jsx的{}中要写表达式,就像可以写三元表达式但不能写if语句,详情见以前的博客 jsx语法规则
  • 对象中的扩展运算符(…)用于取出参数对象中的所有可遍历属性,拷贝到当前对象之中
  • 遍历时要有唯一key值

4.拓展:用fetch发送网络请求(关注分离)

// 用fetch发送请求 (未优化)
        fetch(`http://localhost:3000/api1//search/users2?q=${inputElement.value}`).then(
            response => {
                console.log('联系服务器成功了');
                return response.json()
            },
            error => {
                console.log('联系服务器失败了',error);
                return new Promise(()=>{})
            }
        ).then(
            response => {
                console.log('获取数据成功了',response)
            },
            error => {
                console.log('获取数据失败了',error)
            }
        ).catch(
            error => {
                console.log(error)
            }
        )
// 用fetch发送网络请求(优化)
        try {
            const response = await fetch(`http://localhost:3000/api1//search/users?q=${inputElement.value}`)
            const data = await response.json()
            this.props.updateAppState({isLoading: false, users: data.items})
        } catch (error) {
            console.log('请求出错',error)
        }

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值