2019年最新 React从入门到实战(带 React 企业级实战项目-宜居)
(React-Redux基础知识&)
React-Redux基础知识&
41.Redux 回顾组件传递及Redux介绍
(Redux 回顾组件传递及Redux介绍&)
Redux 回顾组件传递及Redux介绍&
父传子
子传父
接收数据
默认什么都没有点击传值
普通情况只能组件间传递数据,redux子组件把数据传递给仓库,store负责把数据分发各个组件
把数据提交到公共的stroe仓库中
组件间通信
src\components\coms\Parent.jsx
import React from "react"
import Child from "./Child"
export default class Parent extends React.Component{
state = {
value:""
}
clickHandle = (data) =>{
this.setState({
value:data
})
}
render(){
return(
Parent:{ this.state.value }
)
}
}
src\components\coms\Child.jsx
import React from "react"
export default class Child extends React.Component{
clickHandle = (e) =>{
this.props.onMyEvent("父标题");
}
render(){
return(
Child:{ this.props.title }
)
}
}
App.js
import React from 'react';
import Parent from "./components/coms/Parent"
import { connect } from "react-redux"
// import { increment,decrement } from "./actions/counter"
import * as counterActions from "./actions/counter"
import { bindActionCreators } from "redux"
import User from "./components/user"
class App extends React.Component {
render(){
return (
{/* */}
{ this.props.counter }
{/*
*/}
{/*
*/}
);
}
}
const mapStateToProps = (state) =>{
console.log(state);
return{
counter:state.counter
}
}
// const mapDispatchToProps = (dispatch) =>{
// return {
// increment: () => { dispatch(increment()) },
// decrement: () => { dispatch(decrement()) }
// }
// }
const mapDispatchToProps = (dispatch) =>{
return{
counterActions:bindActionCreators(counterActions,dispatch)
}
}
// 先后顺序不能颠倒
export default connect(mapStateToProps,mapDispatchToProps)(App)
index.js
createStore
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { createStore,applyMiddleware } from "redux"
import { composeWithDevTools } from 'redux-devtools-extension';
import logger from "redux-logger"
import thunk from "redux-thunk"
// import reducer from "./reducers/counter"
import { Provider } from "react-redux"
import rootReducer from "./reducers"
// 异步和同步
// 定时器 网络请求
// 中间件
// const logger = store => next => action =>{
// console.log("dispatch->",action);
// let result = next(action); // 加载下一个中间件
// console.log("next state->",store.getState());
// return result;
// }
// const error = store => next => action => {
// try{
// next(action)
// }catch(e){
// console.log("error->",e);
// }
// }
// 创建store仓库
// const store = createStore(rootReducer,{},applyMiddleware(logger,error));
const store = createStore(rootReducer,{},composeWithDevTools(applyMiddleware(logger,thunk)));
// store.subscribe(() => console.log("state:", store.getState()))
// const render = () => {
// ReactDOM.render(
// store.dispatch({ type: "INCREMENT" })}
// onDecrement={() => store.dispatch({ type: "DECREMENT" })}
// value={store.getState()}
// />,
// document.getElementById('root'));
// }
// render();
// store.subscribe(render)
ReactDOM.render(
,
document.getElementById('root'));
42.BootStrap CDN加载
(BootStrap CDN加载&)
BootStrap CDN加载&
CDN加载
引入CDN
编写视图
react-redux-demo\public\index.html
React App
43.Redux 引入Redux
(Redux 引入Redux&)
Redux 引入Redux&
Redux应用的是单一的stroe
Reducer存在stroe中改变状态的方案
Reducer写法,state往仓库中存的状态,默认state为0,action.type不同的状态改变state
Store.dispatch触发来更新state的
reducer点击触发action.type,在App接收触发两个事件,action动作要对应到reducer一样的字符。
监听数据的变化,store.getState读取到数据
subscribe监听数据变化
渲染到页面上
要重新渲染,首先要render()以后每次监听数据变化要重新渲染render
重新渲染render
src\reducers\counter.js
reducer
import * as actions from "../constants"
const counter = ( state = 0,action ) => {
switch(action.type){
case actions.INCREMENT:
// throw new Error("error reducer")
return state + action.num;
case actions.DECREMENT:
return state - action.num;
default:
return state;
}
}
export default counter
src\constants\index.js
// counter
export const INCREMENT = "INCREMENT"
export const DECREMENT = "DECREMENT"
// user
export const FETCH_USER_SUCCESS = "FETCH_USER_SUCCESS"
export const FETCH_USER_REQUEST = "FETCH_USER_REQUEST";
export const FETCH_USER_FAILURE = "FETCH_USER_FAILURE";
44.Redux 引入React-Redux与mapStateToProps读取数据
(Redux 引入React-Redux与mapStateToProps读取数据&)
Redux 引入React-Redux与mapStateToProps读取数据&
组件通过Mouse触发到Provider身上形成多个Actions动作,触发store当中的reducer,reducer就会发生改变,有多少个action就会对应多少store和reducer
Provider用来包裹的关联上redux和react,不要任何的操作了,单纯应用App,需要store对象
通过Provider本身额外的操作,store是刚刚创建的store,通过provider关联react和redux
react-redux
组件中读取数据
通过connect把App组件与redux连接起来。
按钮操作的两个事件,外面没有传递操作事件了。
mapStateToProps对象读取数据的方案,通过state参数,counter中能读到数据,放到connect()中。Connect连接组件与redux,读取数据
mapStateToProps读取数据
State本身就是counter的值
读取数据要从props中读到数据
45.Redux dispatch与mapDispatchToProps修改数据方案
(Redux dispatch与mapDispatchToProps修改数据方案&)
Redux dispatch与mapDispatchToProps修改数据方案&
操作和修改数据通过dispatch,要单独创建action操作,要提取action操作方便后期维护
Return type值
引入action的操作对象
mapDispatchToProps用来分发事件的,dispatch触发事件的
注意Connect的顺序不能颠倒
dispatch触发action
Props中有了increment
通过dispatch触发increment()函数,需要props
没有dispatch可以触发函数,props中有increment函数
src\actions\counter.js
import * as actions from "../constants"
// export function increment(num){
// return{
// type:actions.INCREMENT,
// num
// }
// }
export function increment(num){
return dispatch => {
setTimeout(() =>{
dispatch({
type:actions.INCREMENT,
num
})
},1000)
}
}
export function decrement(num){
return{
type:actions.DECREMENT,
num
}
}
46.Redux bindActionCreators与参数传递
(Redux bindActionCreators与参数传递&)
Redux bindActionCreators与参数传递&
Action中有很多的操作另一种方式,写起来更容易一些
mapDispatchToProps操作方法变简单了,通过bindActionCreators绑定所有的actions
操作方法简单了,操作按钮修改,通过this.props.counterActions中的increment方法操作,事件触发不是触发函数了。
方法的字符串要有reducer的action.type对应,不用写非常多的actions动作。
字符串要对应,通过常量文件夹管理。
常量字符串,action参数传递
直接引用
按照指定数字增加与减少,参数传递,参数传递给了action,操作的是actions
真正操作的是reducer,前后一样可以省略
参数传递,直接通过前台数据传递到后台actions,通过actions响应到reducers,接收数据
src\actions\counter.js
import * as actions from "../constants"
// export function increment(num){
// return{
// type:actions.INCREMENT,
// num
// }
// }
export function increment(num){
return dispatch => {
setTimeout(() =>{
dispatch({
type:actions.INCREMENT,
num
})
},1000)
}
}
export function decrement(num){
return{
type:actions.DECREMENT,
num
}
}
src\reducers\counter.js
import * as actions from "../constants"
const counter = ( state = 0,action ) => {
switch(action.type){
case actions.INCREMENT:
// throw new Error("error reducer")
return state + action.num;
case actions.DECREMENT:
return state - action.num;
default:
return state;
}
}
export default counter
47.Redux combineReducers合并reducer
(Redux combineReducers合并reducer&)
Redux combineReducers合并reducer&
State中有很多条数据,很多数据需要共享,要合并reducer
通过combineReducers来合并reducers
外层引用关系不需要引用reducer了,直接引用rootReducers
此时相当于给counter多加了一个对象,state代表一个对象,要读取state里面的counter
新增User组件在App中引用
User数据也是共享的,为User也创建一系列的数据
State中有多条数据了
combineReducers合并reducers
src\reducers\index.js
import { combineReducers } from "redux"
import counter from "./counter"
import user from "./user"
const rootReducer = combineReducers({
counter,
user
})
export default rootReducer
src\reducers\user.js
import { FETCH_USER_SUCCESS,FETCH_USER_REQUEST, FETCH_USER_FAILURE } from "../constants"
const initialState = {
user:{},
isFetching: false,
error: null,
}
const user = ( state = initialState,action ) => {
switch(action.type){
case FETCH_USER_SUCCESS:
return {
isFetching: false,
error: null,
user: action.user
};
case FETCH_USER_REQUEST:
return {
isFetching: true,
error: null,
user: {}
}
case FETCH_USER_FAILURE:
return {
isFetching: false,
error: action.error,
user: {}
};
default:
return state;
}
}
export default user
App.js
import React from 'react';
import Parent from "./components/coms/Parent"
import { connect } from "react-redux"
// import { increment,decrement } from "./actions/counter"
import * as counterActions from "./actions/counter"
import { bindActionCreators } from "redux"
import User from "./components/user"
class App extends React.Component {
render(){
return (
{/* */}
{ this.props.counter }
{/*
*/}
{/*
*/}
);
}
}
const mapStateToProps = (state) =>{
console.log(state);
return{
counter:state.counter
}
}
// const mapDispatchToProps = (dispatch) =>{
// return {
// increment: () => { dispatch(increment()) },
// decrement: () => { dispatch(decrement()) }
// }
// }
const mapDispatchToProps = (dispatch) =>{
return{
counterActions:bindActionCreators(counterActions,dispatch)
}
}
// 先后顺序不能颠倒
export default connect(mapStateToProps,mapDispatchToProps)(App)
user.jsx
import React from "react"
import { connect } from "react-redux"
import { bindActionCreators } from "redux"
import * as userActions from "../actions/user"
class User extends React.Component{
render(){
const { error, isFetching, user } = this.props.user;
let data;
if (error) {
data = error;
} else if (isFetching) {
data = "Loading...";
} else {
data = user.title;
}
return(
{ data }
User
)
}
}
const mapStateToProps = (state) =>{
return{
user:state.user
}
}
const mapDispatchToProps = (dispatch) =>{
return {
userActions:bindActionCreators(userActions,dispatch)
}
}
export default connect(mapStateToProps,mapDispatchToProps)(User)
48.Redux Redux中间件与第三方中间件logger
(Redux Redux中间件与第三方中间件logger&)
Redux Redux中间件与第三方中间件logger&
logger中间件
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { createStore,applyMiddleware } from "redux"
import { composeWithDevTools } from 'redux-devtools-extension';
import logger from "redux-logger"
import thunk from "redux-thunk"
// import reducer from "./reducers/counter"
import { Provider } from "react-redux"
import rootReducer from "./reducers"
// 异步和同步
// 定时器 网络请求
// 中间件
// const logger = store => next => action =>{
// console.log("dispatch->",action);
// let result = next(action); // 加载下一个中间件
// console.log("next state->",store.getState());
// return result;
// }
// const error = store => next => action => {
// try{
// next(action)
// }catch(e){
// console.log("error->",e);
// }
// }
// 创建store仓库
// const store = createStore(rootReducer,{},applyMiddleware(logger,error));
const store = createStore(rootReducer,{},composeWithDevTools(applyMiddleware(logger,thunk)));
// store.subscribe(() => console.log("state:", store.getState()))
// const render = () => {
// ReactDOM.render(
// store.dispatch({ type: "INCREMENT" })}
// onDecrement={() => store.dispatch({ type: "DECREMENT" })}
// value={store.getState()}
// />,
// document.getElementById('root'));
// }
// render();
// store.subscribe(render)
ReactDOM.render(
,
document.getElementById('root'));
49.Redux Redux异步中间件redux-thunk
(Redux Redux异步中间件redux-thunk&)
Redux Redux异步中间件redux-thunk&
处理数据前经历中间件的处理,再去处理数据,增加一层防护
单一化写法
用户操作记录,next加载中间件,中间件要放在创建仓库store的上面,所有用户操作都会加载中间件
可以有多个中间件
Throw 抛出错误
常用的中间件系统都已经提供了
src\actions\counter.js
redux-thunk异步
import * as actions from "../constants"
// export function increment(num){
// return{
// type:actions.INCREMENT,
// num
// }
// }
export function increment(num){
return dispatch => {
setTimeout(() =>{
dispatch({
type:actions.INCREMENT,
num
})
},1000)
}
}
export function decrement(num){
return{
type:actions.DECREMENT,
num
}
}
src\reducers\users.js
reducer 等待loading状态
import { FETCH_USER_SUCCESS,FETCH_USER_REQUEST, FETCH_USER_FAILURE } from "../constants"
const initialState = {
user:{},
isFetching: false,
error: null,
}
const user = ( state = initialState,action ) => {
switch(action.type){
case FETCH_USER_SUCCESS:
return {
isFetching: false,
error: null,
user: action.user
};
case FETCH_USER_REQUEST:
return {
isFetching: true,
error: null,
user: {}
}
case FETCH_USER_FAILURE:
return {
isFetching: false,
error: action.error,
user: {}
};
default:
return state;
}
}
export default user
src\actions\users.js
thunk网络异步请求,dispatch触发传递数据
import { FETCH_USER_SUCCESS,FETCH_USER_FAILURE,FETCH_USER_REQUEST } from "../constants"
export const fetch_user_failure = (error) => {
return {
type: FETCH_USER_FAILURE,
error
};
};
export const fetch_user = (user) => {
return {
type: FETCH_USER_SUCCESS,
user
}
};
export const fetch_user_request = () => {
return {
type: FETCH_USER_REQUEST
}
};
export const get_user = () =>{
return dispatch =>{
dispatch(fetch_user_request())
fetch("http://iwenwiki.com/api/blueberrypai/getChengpinDetails.php")
.then(res => res.json())
.then(data =>{
dispatch(fetch_user(data.chengpinDetails[0]))
})
.catch(error =>{
dispatch(fetch_user_failure(error));
})
}
}
user.jsx
div的className调整
import React from "react"
import { connect } from "react-redux"
import { bindActionCreators } from "redux"
import * as userActions from "../actions/user"
class User extends React.Component{
render(){
const { error, isFetching, user } = this.props.user;
let data;
if (error) {
data = error;
} else if (isFetching) {
data = "Loading...";
} else {
data = user.title;
}
return(
{ data }
User
)
}
}
const mapStateToProps = (state) =>{
return{
user:state.user
}
}
const mapDispatchToProps = (dispatch) =>{
return {
userActions:bindActionCreators(userActions,dispatch)
}
}
export default connect(mapStateToProps,mapDispatchToProps)(User)
50.Redux Redux-thunk网络请求
(Redux Redux-thunk网络请求&)
Redux Redux-thunk网络请求&
Thunk主要用于处理异步,异步操作有定时器和网络请求
希望延时1s增加值,无论是触发action,都是同一个action,把异步写在aciton中。
Dispatch触发事件。
需要处理异步
引入异步中间件
网络异步请求
修改reducers,修改state的初始,提取出来。State的操作不能直接改变state,success的时候return {}对象从action中读取user对象。
State是只读的,要改变需要返回一个新的state
修改action,单独进行异步操作return dispatch在回调中进行异步操作。
把数据给fetch_user里面,通过dispatch触发。Get_USER前台可以直接调用
通过connect关联redux,最后没有分号,可以读取数据
数据来源于user中的title,通过点击按钮读取数据,通过动作方法来读取数据。
点击user数据发生变化。
51.Redux Redux-thunk请求三种状态
(Redux Redux-thunk请求三种状态&)
Redux Redux-thunk请求三种状态&
网络请求延时,加载等待的过程,调整慢,isFetching等待状态
Actions也对应有三种等待状态
视图中响应,三种状态都赋值给data,只用加载data即可
视图中loading的状态,检查debugger返回是否为true
调用等待
异步都需要dispatch触发,否则无法传递数据
user.js
import { FETCH_USER_SUCCESS,FETCH_USER_REQUEST, FETCH_USER_FAILURE } from "../constants"
const initialState = {
user:{},
isFetching: false,
error: null,
}
const user = ( state = initialState,action ) => {
switch(action.type){
case FETCH_USER_SUCCESS:
return {
isFetching: false,
error: null,
user: action.user
};
case FETCH_USER_REQUEST:
return {
isFetching: true,
error: null,
user: {}
}
case FETCH_USER_FAILURE:
return {
isFetching: false,
error: action.error,
user: {}
};
default:
return state;
}
}
export default user
src\actions\user.js
import { FETCH_USER_SUCCESS,FETCH_USER_FAILURE,FETCH_USER_REQUEST } from "../constants"
export const fetch_user_failure = (error) => {
return {
type: FETCH_USER_FAILURE,
error
};
};
export const fetch_user = (user) => {
return {
type: FETCH_USER_SUCCESS,
user
}
};
export const fetch_user_request = () => {
return {
type: FETCH_USER_REQUEST
}
};
export const get_user = () =>{
return dispatch =>{
dispatch(fetch_user_request())
fetch("http://iwenwiki.com/api/blueberrypai/getChengpinDetails.php")
.then(res => res.json())
.then(data =>{
dispatch(fetch_user(data.chengpinDetails[0]))
})
.catch(error =>{
dispatch(fetch_user_failure(error));
})
}
}
// counter
export const INCREMENT = "INCREMENT"
export const DECREMENT = "DECREMENT"
// user
export const FETCH_USER_SUCCESS = "FETCH_USER_SUCCESS"
export const FETCH_USER_REQUEST = "FETCH_USER_REQUEST";
export const FETCH_USER_FAILURE = "FETCH_USER_FAILURE";
52.Redux Redux调试工具
(Redux Redux调试工具&)
Redux Redux调试工具&
检测redux数据的变化,在Chrome中应用安装即可
通过依赖来启动插件
引用到主入口文件,包裹整个插件
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { createStore,applyMiddleware } from "redux"
import { composeWithDevTools } from 'redux-devtools-extension';
import logger from "redux-logger"
import thunk from "redux-thunk"
// import reducer from "./reducers/counter"
import { Provider } from "react-redux"
import rootReducer from "./reducers"
// 异步和同步
// 定时器 网络请求
// 中间件
// const logger = store => next => action =>{
// console.log("dispatch->",action);
// let result = next(action); // 加载下一个中间件
// console.log("next state->",store.getState());
// return result;
// }
// const error = store => next => action => {
// try{
// next(action)
// }catch(e){
// console.log("error->",e);
// }
// }
// 创建store仓库
// const store = createStore(rootReducer,{},applyMiddleware(logger,error));
const store = createStore(rootReducer,{},composeWithDevTools(applyMiddleware(logger,thunk)));
// store.subscribe(() => console.log("state:", store.getState()))
// const render = () => {
// ReactDOM.render(
// store.dispatch({ type: "INCREMENT" })}
// onDecrement={() => store.dispatch({ type: "DECREMENT" })}
// value={store.getState()}
// />,
// document.getElementById('root'));
// }
// render();
// store.subscribe(render)
ReactDOM.render(
,
document.getElementById('root'));
(React 进阶&)
React 进阶&
1.React 进阶 组件优化1
(组件优化1&)
组件优化1&
parent.jsx
外部需要拿到count的值通过回调函数
回调函数获取定时器中的值,定时器网络请求组件销毁处理
state变化render重新渲染pureComponent
import React from "react"
import Child from "./child"
import Child1 from "./child1"
/**
* 计数例子
*
* 定时器
* 网络请求
* 事件监听
* 在组件被销毁前都应得到相应的处理
*
*/
const MyAPI = {
count:0,
subscribe(cb){
this.intervalId = setInterval(() =>{
this.count += 1
cb(this.count);
},1000)
},
unSubscribe(){
clearInterval(this.intervalId);
this.reset();
},
reset(){
this.count = 0;
}
}
export default class Parent extends React.Component {
state = {
count:0
}
componentDidMount(){
MyAPI.subscribe((currentCount) =>{
this.setState({
count:currentCount
})
})
}
componentWillUnmount(){
MyAPI.unSubscribe();
}
render() {
console.log("parent -> render");
return (
Parent:{ this.state.count }
)
}
}
child1.jsx 不通过生命周期方式进行处理
import React from 'react';
/**
* Component:不会对数据进行比较
* PureComponent:对数据进行浅比较 props
*
*/
export default class Child1 extends React.PureComponent {
render() {
console.log("child1 -> render");
return (
Child1:{ this.props.num }
);
}
}
child.jsx state发生改变render重新渲染,整个Child重新渲染,通过生命周期Child不用渲染
shouldComponentUpdate
import React from 'react';
export default class Child extends React.Component {
/**
*
* @param {*} nextProps
* @param {*} nextState
*
* 关于渲染问题
*/
shouldComponentUpdate(nextProps,nextState){
if(nextProps.num === this.props.num){
return false;
}
return true;
}
render() {
console.log("child -> render");
return (
Child:{ this.props.num }
);
}
}
App.js
HashRouter
import React from 'react';
import Demo1 from "./components/Demo1/parent"
import Home from "./components/Home"
import { HashRouter, Route, Switch } from "react-router-dom"
function App() {
return (
);
}
export default App;
Home.jsx
import React from 'react';
import Demo2 from "./Demo2"
import Demo3 from "./Demo3"
import Demo4 from "./Demo4"
import Banner from "./Demo5/banner"
import Chengpin from "./Demo5/chengpin"
import NewBanner from "./Demo5/New/NewBanner"
import NewChengpin from "./Demo5/New/NewChengpin"
import Demo6 from "./Demo6/Parent"
function Home() {
return (
);
}
export default Home;
2.React 进阶 组件优化2
(组件优化2&)
组件优化2&
index.jsx,列表数据动态生成
Fragment返回li
import React,{ Fragment } from "react"
class Item extends React.Component {
render() {
return (
Demo2 Item1
Demo2 Item1
)
}
}
export default class Demo2 extends React.Component {
render() {
return (
)
}
}
3.React 进阶 组件优化3
(组件优化3&)
组件优化3&
index.jsx color只有在comment中使用,context上下文对象,getChildContext系统提供方法,context对象直接传递history不用两次传递
context孙子组件通信传递history
import React from "react"
import PropTypes from "prop-types"
const Topic = (props) =>{
return(
)
}
/**
*
* 路由:this.props.history.push("/"):必须是路由直接子元素,如果是孙子元素,则不能使用
*
* withRouter
*
*/
const Comment = (props,context) =>{
return(
{ context.color }
)
}
export default class Demo3 extends React.Component{
getChildContext(){
return{
color:"red"
}
}
render(){
return(
)
}
}
Comment.contextTypes = {
color:PropTypes.string
}
Demo3.childContextTypes = {
color:PropTypes.string
}
4.React 进阶 Fragment
(React 进阶 Fragment&)
React 进阶 Fragment&
5.React 进阶 Context
(React 进阶 Context&)
React 进阶 Context&
6.React 进阶 高阶组件
(React 进阶 高阶组件&)
React 进阶 高阶组件&
index.jsx 可以在高阶组件中对MyData进行处理
高阶组件定义,
import React from "react"
/**
*
* 高阶组件
* 1.函数
* 2.参数一个组件
* 3.返回值也是一个组件
*/
const withFetch = (ComposeComponent) =>{
return class extends React.Component{
render(){
return(
)
}
}
}
class MyData extends React.Component{
render(){
return(
MyData:{this.props.data}
)
}
}
const WithFetch = withFetch(MyData);
export default class Demo4 extends React.Component{
render(){
return(
)
}
}
7.React 进阶 高阶组件应用
(React 进阶 高阶组件应用&)
React 进阶 高阶组件应用&
banner组件与chengpin组件出了url不同其他都一样
相似组件通过高阶组件优化处理
banner.jsx
import React, { Component } from 'react';
class Banner extends Component {
constructor() {
super();
this.state = {
loading: true,
banner: null
};
}
componentDidMount() {
fetch('http://iwenwiki.com/api/blueberrypai/getIndexBanner.php')
.then(res => res.json())
.then(banner => {
this.setState({
loading: false,
banner: banner
});
})
}
render() {
if(this.state.loading) {
return (
loading
)
} else {
return (
{this.state.banner.banner[0].title}
)
}
}
}
export default Banner;
chengpin.jsx
import React, { Component } from 'react';
class Chengpin extends Component {
constructor() {
super();
this.state = {
loading: true,
chengpin: null
};
}
componentDidMount() {
fetch('http://iwenwiki.com/api/blueberrypai/getChengpinInfo.php')
.then(res => res.json())
.then(chengpin => {
this.setState({
loading: false,
chengpin: chengpin
});
})
}
render() {
if(this.state.loading) {
return (
loading
)
} else {
return (
{this.state.chengpin.chengpinInfo[0].title}
)
}
}
}
export default Chengpin;
withFetch.jsx return两个函数
import React,{Component} from 'react'
const withFetch = (url) => (View) => {
return class extends Component {
constructor() {
super();
this.state = {
loading: true,
data: null
}
}
componentDidMount() {
fetch(url)
.then(res => res.json())
.then(data => {
this.setState({
loading: false,
data: data
});
})
}
render(){
if(this.state.loading){
return(
loadding....
)
}else{
return
}
}
}
}
export default withFetch
NewBanner.jsx,有两个参数第二个参数是组建视图,相同得到放到高阶组件处理
import React from "react"
import withFetch from "../withFetch"
const Banner = withFetch("http://iwenwiki.com/api/blueberrypai/getIndexBanner.php")(props =>{
return(
{ props.data.banner[0].title }
)
})
export default Banner;
NewChengpin.jsx
import React from "react"
import withFetch from "../withFetch"
const Chengpin = withFetch("http://iwenwiki.com/api/blueberrypai/getChengpinInfo.php")(props =>{
return(
{ props.data.chengpinInfo[0].title }
)
})
export default Chengpin;
8.React 进阶 错误边界处理
(React 进阶 错误边界处理&)
React 进阶 错误边界处理&
Parent.jsx
import React from 'react'
import Errors from "./Errors"
import ErrorBoundary from "./ErrorBoundary"
export default class Parent extends React.Component{
state = {
count:0
}
increment = () =>{
this.setState({
count:this.state.count+1
})
}
decrement = () =>{
this.setState({
count:this.state.count-1
})
}
render(){
return(
这是一个标题
{ this.state.count }
{ '加载时发生错误' }
}>
)
}
}
Errors.jsx
错误边界componentDidCatch
import React from 'react'
export default class Errors extends React.Component{
render(){
return(
{
null.map((element,index) =>{
return - { element }
})
}
)
}
}
ErrorBoundary.jsx
import React from "react"
export default class ErrorBoundary extends React.Component{
state = {
hasError:false,
error:null,
errorInfo:null
}
/**
* 子元素发生错误时触发
*/
componentDidCatch(error,errorInfo){
this.setState({
hasError:true,
error:error,
errorInfo:errorInfo
})
}
render(){
if(this.state.hasError){
return { this.props.render(this.state.error,this.state.errorInfo) }
}
return this.props.children;
}
}
(React&Redux实战-登录注册认证&)
React&Redux实战-登录注册认证&
(React 企业级实战项目-宜居&)
React 企业级实战项目-宜居&