React入门(五)之状态树传参

1、context 状态树传参

1.1、解释

​ Context 旨在共享一个组件树,可被视为 “全局” 的数据,达到越级传递

场景:当前经过身份验证的用户,主题或首选语言,包括管理当前的 locale,theme,或者一些缓存数据。

  • createContext():

    用于创建context对象(上下文),需要一个defaultValue的参数,并返回一个包含Provider(提供者),以及Consumer(消费者)的对象。

  • Provider:

    提供者,提供数据。接收一个将要被往下层层传递的props,该值需在组件树最顶层设置。一个Provider可以关联到多个Consumers。这是一个顶层用于提供context的组件,包含一个value的props,value是实际的context数据。

  • Consumer:

    消费者,使用者,接收一个函数作为子节点,函数接收当前 context 的值。这是一个底层用于获取context的组件,需要一个函数作为其子元素,该函数包含一个value的参数,这个参数就是上层所传递context value

创建一个context组件,并设定默认值:

const {Provider,Consumer} = React.createContext(defaultValue);

1.2、从父朝子传值(外朝内)

示例代码:

// context组件: 项目根目录下新建utils/myContext;

import {createContext} from "react";
export const {Provider, Consumer} = createContext({
  name:"张三疯"
});

//顶层组件:./src/App.js

import {Provider} from "./utils/myContext"

function App() {
  let val={
    name:"hi"
  };
  return (
    <div className="App">
      <Provider value={val}>
        <Home  />
      </Provider>
    </div>
  );
}

//孙子组件: 在Home组件及子孙组件都可获取值

import {Consumer} from "../utils/myContext";

export default class GoodsList extends React.Component {
   
    render = () => (
        <div className="goodsList-box">
            <h1>商品列表:</h1>            
            <Consumer>
                    {
 					  (val)  => <div> { val.name } </div>
					}
            </Consumer>
        </div>
    )
}

注意:

export const {Provider, Consumer} = createContext({
​      name:"晓晓"
});

这个默认值是在顶层组件没有使用Provider组件时的值,而不是,没有给value属性赋值时的值。

也就是说:当顶层组件的代码如下时,默认值为'晓晓’:

function App() {
  let val={
      name:"hi"
  };
  return (
    <div className="App">  
         <Home />
    </div>
  );
}

1.3、在子组件改变状态树的数据

//根组件:
import {Provider} from "./utils/myContext"

export default class App extends React.Component {
  constructor(props){
    super(props);  
    this.state={
        name:"宋晨",
        setName:this.fn
    } 
  }

  fn=(str)=>{
      this.setState({
        name:str
      });
  }
  
  render = () => (
    <div className="App">
      <Provider value={this.state} >
        <Home />
      </Provider>
    </div>
  )
}

//子组件里:
import {Consumer} from "../../utils/myContext";

export default class Banner extends Component {

render = () => (
  <div className="box" >
     <Consumer>
        {
           (obj)=>(
              <div>
                 <p>姓名:{obj.name}</p>
                  <input type="button" value="修改" onClick={()=>obj.setName("hiwww")} />
              </div>
          )
        }
        </Consumer>
    </div>
   )
}

2、高阶组件(HOC)的构建与应用

​ 高阶组件(HOC)是react中对组件逻辑进行重用的高级技术。但高阶组件本身并不是React API。它只是一种模式,这种模式是由react自身的组合性质必然产生的。

​简单来说,高阶组件就是一个函数,且该函数接受一个组件作为参数,并返回一个新的组件,高阶组件会对传入的组件做一些通用的处理。比如:我们希望给组件的的下方增加一个版权信息,那么就可以使用高阶组件。把原始组件传入,然后,给组件增加一个版权信息后,再返回。

​ 高阶组件是通过将原组件 包裹(wrapping) 在容器组件(container component)里面的方式来组合(composes) 使用原组件。高阶组件就是一个没有副作用的纯函数。

如:

const EnhancedComponent = higherOrderComponent(WrappedComponent);

	高阶函数是:higherOrderComponent
	传入的组件是:WrappedComponent
	返回的组件是:EnhancedComponent

示例代码:

// 带上版权的高阶函数
function withCopyRight(OldCom){
    
    class NewCom extends React.Component{      
        render() {
            return (
               <div>
                    <OldCom />
                    <hr/>
                    <div>
                        Copyright © 2020 Sohu All Rights Reserved. 版权所有
                    </div>
               </div>
            );
        }
    }   
    
    return NewCom;
}

//原始组件
class CommentList extends React.Component {
  render() {      
    return (
        <div>
            今天天气不错
        </div>
    );
  }
}

//调用高阶函数后的组件
const CommentListWithCopyRight = withCopyRight(CommentList);

ReactDOM.render( <div> <CommentListWithCopyRight /></div> ,$("box"));
function $(id){
    return document.getElementById(id);
}

注意(重要):

1、不要在render函数里使用高阶组件

2、必须将静态(static)方法做拷贝

​ 当使用高阶组件包装组件,原始组件被容器组件包裹,也就意味着新组件会丢失原始组件的所有静态方法,解决这个问题的方法就是,将原始组件的所有静态方法全部拷贝给新组件。

3、Refs不能传递

一般来说,高阶组件可以传递所有的props属性给包裹的组件,但是不能传递refs引用。

4、不要在高阶组件内部修改(或以其它方式修改)原组件的原型属性(prototype)。

5、约定:将不相关的props属性传递给包裹组件

6、约定:最大化使用组合

7、约定:包装显示名字以便于调试

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值