Hook、Context知识

Hook

是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。
在这里插入图片描述
State Hook
useState 唯一的参数就是初始 state。
可以声明多个 state 变量在这里插入图片描述
Effect Hook
useEffect 是一个 Effect Hook,给函数组件增加了操作副作用的能力。
在这里插入图片描述
副作用函数还可以通过返回一个函数来指定如何“清除”副作用。
在这里插入图片描述
useState 一样,你可以在组件中多次使用 useEffect
在这里插入图片描述

自定义 Hook
在这里插入图片描述
在两个组件中使用它:
在这里插入图片描述

Hook 使用规则

  • 只能在函数最外层调用 Hook。不要在循环、条件判断或者子函数中调用。
  • 只能在 React 的函数组件中调用 Hook。不要在其他 JavaScript 函数中调用

初识Context

Context 通过组件树提供了一个传递数据的方法,从而避免了在每一个层级手动的传递 props 属性。context可以实现跨层级进行数据传递。

context api 给出三个概念:
React.createContext()、Provider、Consumer;

  • React.createContext()
    这个方法用来创建context对象,并包含Provider、Consumer两个组件 <Provider />、<Consumer />, defaultValue可以设置共享的默认数据
const {Provider, Consumer} = React.createContext(defaultValue);
  • Provider

数据的生产者,用来传递给子组件或后代组件。value:放置共享的数据。

<Provider 
	value={/*共享的数据*/}>
    /*里面可以渲染对应的内容*/
</Provider>
  • Consumer
    数据的消费者,通过订阅Provider传入的context的值,来实时更新当前组件的状态。
<Consumer>
  {value => /*根据上下文  进行渲染相应内容*/}
</Consumer>

怎么样使用Context?

Context的使用主要分为创建、插入、访问三个流程,通过创建context对象提供共享组件,将Provider指定嵌套至需要使用共享数据的顶层结构,然后各后代组件通过context访问共享数据(变量、常量、方法等)。

创建一个context

// 创建文件LoginContext.js
import { createContext } from 'react';
const LoginContext = createContext({});
export default LoginContext;

Provider包装一个组件

//创建一个LoginFrom.js
import { Tabs, Form } from 'antd';
import React, { useState } from 'react';
import useMergeValue from 'use-merge-value';
import classNames from 'classnames';
import LoginContext from './LoginContext';
import LoginItem from './LoginItem';
import LoginSubmit from './LoginSubmit';
import LoginTab from './LoginTab';
import styles from './index.less';

const Login = props => {
  const { className } = props;
  const [tabs, setTabs] = useState([]);
  const [active, setActive] = useState();
  const [type, setType] = useMergeValue('', {
    value: props.activeKey,
    onChange: props.onTabChange,
  });
  const TabChildren = [];
  const otherChildren = [];
  React.Children.forEach(props.children, child => {
    if (!child) {
      return;
    }

    if (child.type.typeName === 'LoginTab') {
      TabChildren.push(child);
    } else {
      otherChildren.push(child);
    }
  });
  return (
    <LoginContext.Provider
      value={{
        tabUtil: {
          addTab: id => {
            setTabs([...tabs, id]);
          },
          removeTab: id => {
            setTabs(tabs.filter(currentId => currentId !== id));
          },
        },
        updateActive: activeItem => {
          if (active[type]) {
            active[type].push(activeItem);
          } else {
            active[type] = [activeItem];
          }

          setActive(active);
        },
      }}
    >
      <div className={classNames(className, styles.login)}>
        <Form
          form={props.from}
          onFinish={values => {
            if (props.onSubmit) {
              props.onSubmit(values);
            }
          }}
        >
          {tabs.length ? (
            <React.Fragment>
              <Tabs
                animated={false}
                className={styles.tabs}
                activeKey={type}
                onChange={activeKey => {
                  setType(activeKey);
                }}
              >
                {TabChildren}
              </Tabs>
              {otherChildren}
            </React.Fragment>
          ) : (
            props.children
          )}
        </Form>
      </div>
    </LoginContext.Provider>
  );
};

Login.Tab = LoginTab;
Login.Submit = LoginSubmit;
Login.UserName = LoginItem.UserName;
Login.Password = LoginItem.Password;
Login.Mobile = LoginItem.Mobile;
Login.Captcha = LoginItem.Captcha;
export default Login;

调用共享数据

//创建文件LoginTab.js
import React, { useEffect } from 'react';
import { Tabs } from 'antd';
import LoginContext from './LoginContext'; // 创建的共享context

const { TabPane } = Tabs;

const generateId = (() => {
  let i = 0;
  return (prefix = '') => {
    i += 1;
    return `${prefix}${i}`;
  };
})();

const LoginTab = props => {
  useEffect(() => {
    const uniqueId = generateId('login-tab-');
    const { tabUtil } = props;

    if (tabUtil) {
      tabUtil.addTab(uniqueId);
    }
  }, []);
  const { children } = props;
  return <TabPane {...props}>{props.active && children}</TabPane>;
};

const WrapContext = props => (
  <LoginContext.Consumer>
    {value => <LoginTab tabUtil={value.tabUtil} {...props} />}
  </LoginContext.Consumer>
); // 标志位 用来判断是不是自定义组件

WrapContext.typeName = 'LoginTab';
export default WrapContext;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值