local state的管理
- 之前讨论的 redux、rematch、easy-peasy 都是全局的状态管理
- 对于大部分的简单业务,local state的管理并不麻烦,基本上就是控制一些弹窗的展示,loading的展示等
常见例子
- 例子中的逻辑是一个组件获取接口数据,并根据接口状态展示不同信息;
- 例子中是一个class组件,组件中既包含view视图,又包含model数据处理(状态存储和状态修改逻辑)
- 这样的写法优点是逻辑紧密关联,易于理解;缺点是逻辑难以复用javascript1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41import React from 'react'; 
 import axios from 'axios'
 class PageA extends React.Component {
 /**
 * loading 是否显示loading
 * data 数据
 * err 请求错误
 */
 state = {
 loading: false,
 data: null,
 err: null
 }
 async componentDidMount() {
 this.setState({ loading: true })
 try {
 const res = await axios.get('/api/pageA/options')
 this.setState({
 loading: false,
 data: res.data.data,
 })
 } catch (err) {
 this.setState({
 loading: false,
 error: err.message
 })
 }
 }
 render() {
 if (this.state.loading) {
 return <div>loading....</div>
 } else {
 return <div>{this.state.data}</div>
 }
 }
 }
 export default PageA;
class组件的逻辑复用:容器组件和视图组件分离
视图组件复用
- 容器组件只负责处理状态
- 视图组件之负责展示
- 一般UI组件库使用这种方式javascript1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49import React from 'react'; 
 import axios from 'axios'
 // 视图组件
 class Loading extends React.Component {
 render() {
 if (this.props.loading) {
 return <div>loading....</div>
 } else {
 return <div>{this.props.data}</div>
 }
 }
 }
 // 容器组件
 class PageA extends React.Component {
 /**
 * loading 是否显示loading
 * data 数据
 * err 请求错误
 */
 state = {
 loading: false,
 data: null,
 err: null
 }
 async componentDidMount() {
 this.setState({ loading: true })
 try {
 const res = await axios.get('/api/pageA/options')
 this.setState({
 loading: false,
 data: res.data.data,
 })
 } catch (err) {
 this.setState({
 loading: false,
 error: err.message
 })
 }
 }
 render() {
 return <Loading {...this.state}></Loading>
 }
 }
 export default PageA;
容器组件复用
- 高阶组件HOCTypescript的支持并不友好,代码可读性差javascript1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51import React from 'react'; 
 import axios from 'axios'
 // 视图组件
 class Loading extends React.Component {
 render() {
 if (this.props.loading) {
 return <div>loading....</div>
 } else {
 return <div>{this.props.data}</div>
 }
 }
 }
 // 容器组件
 function withLoading(Component) {
 return class PageA extends React.Component {
 /**
 * loading 是否显示loading
 * data 数据
 * err 请求错误
 */
 state = {
 loading: false,
 data: null,
 err: null
 }
 async componentDidMount() {
 this.setState({ loading: true })
 try {
 const res = await axios.get('/api/pageA/options')
 this.setState({
 loading: false,
 data: res.data.data,
 })
 } catch (err) {
 this.setState({
 loading: false,
 error: err.message
 })
 }
 }
 render() {
 return <Component {...this.state}></Component>
 }
 }
 }
 export default withLoading(Loading);
- renderProps会导致嵌套过多javascript1 
 2
 3
 4
 5<WithLoading> 
 {(props) => {
 <Loading {...props} />
 }}
 </WithLoading>
React Hook 实现逻辑复用
优势
- React Hook的一大特色就是状态逻辑复用
- 而且社区上已经积攒了很多的hook可以直接使用javascript1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33import React, { useState, useEffect } from 'react'; 
 import axios from 'axios'
 function useLoading() {
 const [loading, setLoading] = useState(false);
 const [error, setError] = useState(null);
 const [data, setData] = useState(null);
 useEffect(() => {
 setLoading(true);
 axios.get('/api/pageA/options').then(res => {
 setLoading(false);
 setData(res.data.data);
 }).catch(err => {
 setLoading(false);
 setError(err.message)
 })
 }, [])
 return [loading, error, data]
 }
 function PageA() {
 const [loading, error, data] = useLoading();
 if (loading) {
 return <div>loading....</div>
 } else {
 return <div>{data}</div>
 }
 }
 export default PageA;
不足
- 在function里组织业务代码,调用函数的时候需要注意函数声明的顺序
- 需要规范hook代码顺序javascript1 
 2
 3
 4
 5
 6function APP(){ 
 // 1. useState, useRef
 // 2. 组件函数
 // 3. useEffect
 // 4. render逻辑
 }




