实现效果
获取到的数据
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