React通过天气预报API获取数据

时间:2021-1-8 作者:admin
实现效果

获取到的数据

redux可视化工具

通过晒选框显示想要的数据,或7天的数据,可以自定义条件

1.文件层级

2.index.jsx入口文件

入口文件和正常书写React一样

import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'

// 入口文件
ReactDOM.render(<App></App>, document.getElementById('root'))
3.App.jsx根组件

这里需要从react-redux包中引入Provider组件,将需要使用redux的根组件包裹起来

  • Provider在一个整体组件中只需要使用一次
  • Provider要写store属性,属性值为store对象
import React, { Component } from 'react'
import { Provider } from 'react-redux'
import store from './redux/store'
import List from './contiants/WithList'
import Search from './pages/search'

export default class App extends Component {
    render() {
        return (
            // 需要使用到redux的state,需要使用Provider将根组件包裹
            <Provider store={store}>
                <div>
                    {/* Search使用的是展示组件 */}
                    <Search></Search>
                    {/* List使用的是容器组件来渲染 */}
                    <List></List>
                </div>
            </Provider>
        )
    }
}

4.pages文件夹中的search.jsx

这里写search搜索栏的结构

  • 这里面需要将input设为受控组件,按钮设置了点击事件
  • 每次点击事件都触发handle_pub函数,将input的值通过pubsub的publish将数据发布出去
import React, { Component } from 'react'
import pubsub from 'pubsub-js'
import './index.css'
export default class index extends Component {
    state = {
        data: ''
    }
    // 按钮点击后topick发布,List组件中去订阅topick,接收search的state
    handle_pub = () => {
        pubsub.publish("topick", this.state.data)
    }
    handle_input = (e) => {
        this.setState({
            data: e.target.value
        })
    }
    render() {
        return (
            <div className='input'>
                请输入搜索内容
                <input type="text" value={this.state.data} onChange={this.handle_input} />
                <button onClick={this.handle_pub}>搜索</button>
            </div>
        )
    }
}
5.pages文件夹中的List.jsx展示组件

这里的注意点是,我们在拿到search的值后,需要将这个值通过异步action发送异步ajax去拿到服务器的数据

import React, { Component } from 'react'
import pubsub from 'pubsub-js'
import './index.css'

export default class index extends Component {
    state = {
        week: ''
    }
    weekChange = data => () => { this.props.set_week(data) }
    handleChange = (e) => {
        this.setState({
            week: e.target.value
        })
    }
    render() {
        let newUser = [...this.props.user]
        // 筛选星期几的天气,可以自己加判断条件
        if (this.props.week === "星期一") {
            newUser = newUser.filter((user) => {
                return user.week === "星期一"
            })
        }
        if (newUser.length > 0) {
            return (
                <>
                    <input type="text" value={this.state.week} onChange={this.handleChange} />
                    <button onClick={this.weekChange(`星期${this.state.week}`)}>提交</button>
                    <button onClick={this.weekChange('all')}>七天</button>
                    <div>
                        {/* 获取到通过容器组件传过来的数组,映射到一个新数组中,渲染出来 */}
                        {newUser.map((user, index) => {
                            return (
                                <ul key={index}>
                                    <li>{user.day}</li>
                                    <li>{user.date}</li>
                                    <li>{user.week}</li>
                                    <li>{user.wea}</li>
                                </ul>
                            )
                        })}
                    </div>
                </>
            )
        }
        return null
    }

    // 当组件创建成功后,订阅topick,从search那获取到数据
    componentDidMount() {
        pubsub.subscribe("topick", (msg, data) => {
            // 调用从WithList容器组件中获取到的get_user_async方法,这里的data数据会在actions.js中传传入到异步的action去中执行异步ajax请求
            this.props.get_user_async(data)
        })
    }
    // 组件即将销毁时,取消订阅
    componentWillUnmount() {
        pubsub.unsubscribe("topick")
    }
}
6.WithList.js容器组件

这里需要从react-redux包中获取到connect,创建一个List的容器组件,通过调用connect可以向展示组件传递数据和操作数据的值

connect:

  • 第一个调用是传入映射数据的方法和action,第二个调用是传入展示组件
  • connect会在创建的时候调用一次,给展示组件传递最新的值
  • 在每次redux数据更新的时候,connect都会调用一次,给展示组件传值
import { connect } from 'react-redux'
import List from '../pages/list'
import { get_user_async, get_user, set_week } from '../redux/actions'
// 映射redux的state到展示组件中,展示组件通过this.props可以获取到
const map_state_to_props = state => {
    return {
        user: state.user_reducer.user,
        week: state.week_reducer.week
    }
}
// 给展示组件传递redux的数据,和操作这些数据的方法
// 在connect第一次调用的第二个参数中,传入的是action,内部会帮我们封装一个函数,函数名和action名一样
const With_List = connect(map_state_to_props, { get_user_async, get_user, set_week })(List)
export default With_List
7.redux/reducers的user_reducer.js
import { USER_GET_SUCCESS} from '../constants'

// 初始化state
let init_state = {
    user: []
}

export default function user_reducer(state = init_state, action) {
    switch (action.type) {
        case USER_GET_SUCCESS:
            return {
                ...state,
                user: action.data
            }
        default:
            return state
    }
}
7.redux/reducers的week_reducer.js

这里是为了做星期筛选准备的,通过获取到week的值来筛选天气信息

import {SET_WEEK } from '../constants'

// 初始化state
let init_state = {
    week: 'all'
}

export default function user_reducer(state = init_state, action) {
    switch (action.type) {
        case SET_WEEK:
            return {
                ...state,
                week: action.data
            }
        default:
            return state
    }
}
8.redux的actions.js

reducer执行对应的执行条件,异步操作也是写在action中

import { USER_GET_SUCCESS, SET_WEEK } from './constants'
import axios from 'axios'
// 同步action,用来修改redux数据
function get_user(data) {
    return { type: USER_GET_SUCCESS, data }
}
// 异步的action,用来向服务器发请求
function get_user_async(data) {
    return dispatch => {
        // 异步ajax发送请求
        axios.get(
            "http://www.tianqiapi.com/api?version=v9&appid=xxxxx&appsecret=xxxxxx",
            {
                params: {
                    city: data
                }
            }
        ).then(res => {
            console.log('请求成功', res)
            // 将返回的数据放到同步action中,去执行reducer
            dispatch(get_user(res.data.data))
        }).catch(err => {
            console.log(err)
        })
    }
}
// 同步action,用来显示指定星期几的
function set_week(data) {
    return { type: SET_WEEK, data }
}
export { get_user, get_user_async, set_week }
9.redux的constants.js

设置一些常量,方便后期维护

const USER_GET_SUCCESS = 'USER_GET_SUCCESS'
const SET_WEEK = 'SET_WEEK'
export { USER_GET_SUCCESS, SET_WEEK }
10.redux的store.js
import { createStore, applyMiddleware, combineReducers } from 'redux'
import { composeWithDevTools } from 'redux-devtools-extension/logOnlyInProduction';
import user_reducer from './reducers/user_reducer'
import week_reducer from './reducers/week_reducer'
import thunk from 'redux-thunk'

// 合并reducer
const root_reducer = combineReducers({
    user_reducer,
    week_reducer
})
// 传入根reducer和thunk中间件,中间件需要使用applyMiddleware来引入
// thunk中间件可以让我们在redux中做异步的操作
// composeWithDevTools是一个redux可视化调试工具,可以参考https://github.com/zalmoxisus/redux-devtools-extension文档使用
const store = createStore(root_reducer, composeWithDevTools(applyMiddleware(thunk)))
export default store
声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。