React 之 专题(React Hooks、Fomik、CSS-IN-JS、Chakra-UI )

React 之 专题(React Hooks)

1、React Hooks 介绍

1.1 React Hooks 是用来做什么的

对函数型组件进行增强, 让函数型组件可以存储状态, 可以拥有处理副作用的能力.

让开发者在不使用类组件的情况下, 实现相同的功能.

1.2 类组件的不足 (Hooks 要解决的问题)

  1. 缺少逻辑复用机制
  • 为了复用逻辑增加无实际渲染效果的组件,增加了组件层级 代码显示十分臃肿
  • 增加了调试的难度以及运行效率的降低
  1. 类组件经常会变得很复杂难以维护
  • 将一组相干的业务逻辑拆分到了多个生命周期函数中 (与Vue2.0相似,Vue3.0就增加了Composition API (组合式 API)来解决此问题)
  • 在一个生命周期函数内存在多个不相干的业务逻辑
  1. 类成员方法不能保证this指向的正确性
    经常要使用 bing 或者 嵌套函数来保证,使得代码看起来复杂;

2、 React Hooks 使用

Hooks 意为钩子, React Hooks 就是一堆钩子函数, React 通过这些钩子函数对函数型组件进行增强, 不同的钩子函数提供了不同的功能.

  • useState()
  • useEffects()
  • useReducer()
  • useRef()
  • useCallback()
  • useContext()
  • useMemo()

2.1 useState()

用于为函数组件引入状态

import React, {
      useState } from 'react';

function App () {
     
	const [count, setCount ] = useState(0);
	return <div>
		<span>{
     count}</span>
		<button onClick={
     () => setCount(count + 1)}> +1 </button>
	</div>;
}

使用说明:

  1. 接收唯一的参数即状态初始值. 初始值可以是任意数据类型.
  2. 返回值为数组. 数组中存储状态值和更改状态值的方法. 方法名称约定以set开头, 后面加上状态名称.
  3. 方法可以被调用多次. 用以保存不同状态值.
  4. 参数可以是一个函数, 函数返回什么, 初始状态就是什么, 函数只会被调用一次, 用在初始值是动态值的情况.

设置状态值方法的参数可以是一个值也可以是一个函数.
设置状态值方法的方法本身是异步的.

import React, {
      useState } from 'react';

function App () {
     
  const [ count, setCount] = useState (0)
  const [ person, setPerson] = useState ({
      name: "张三", age: 20})
	function handlecount() {
     
	  setCount (count => {
     
	  	return count + 1
	  })
	}
	document.title= count
  return  <div>
	<span>{
     count} {
     person.name} {
     person.age}</span>   
	<button onClick={
     handlecount}>+ 1</button>
	<button onclick={
      () => setPerson({
     ...person, name:"李四"}) }> setperson </button>
  </div>
}

2.2 useReducer()

useReducer是另一种让函数组件保存状态的方式.

import React, {
      useReducer } from  'react';


function App () {
     
    function reducer  (state, action) (
	  switch (action.type) {
     
	    case 'increment':
		  return state + 1
	  }
	}
	const [ count, dispatch ] = useReducer(reducer, 0)
	return  <div>
		<span>{
      count }</span>
		<button onClick={
      () => dispatch({
      type: 'increment' })}> +1</button>
	</div>
}

2.3 useContext()

在跨组件层级获取数据时简化获取数据的代码.

import {
      createContext, useContext } from 'react';
const countcontext = createContext();
function App() {
     
  return (
    <countcontext.Provider value={
     100}>
      <Toolbar />
    </countcontext.Provider>
  );
}

function Toolbar() {
     
  const value = useContext(countcontext);  
  return <div>{
     value}</div>;
}

2.4 useEffect()

让函数型组件拥有处理副作用的能力. 类似生命周期函数.

  1. useEffect 执行时机
    可以把 useEffect 看做 componentDidMount, componentDidUpdate 和 componentWillUnmount 这三个函数的组合. 有三种情况
  • useEffect(() => {}) => componentDidMount, componentDidUpdate 组件挂载完成执行一次 组件数据更新完成之后执行
  • useEffect(() => {}, []) => componentDidMount 组件挂载完成执行一次
  • useEffect(() => () => {}) => componentWillUnMount 组件被卸载之前执行
  1. useEffect 使用方法

为window对象添加滚动事件,组件卸载时移除
设置定时器让count数值每隔一秒增加1 ,组件卸载时清除定时器

  1. useEffect 解决的问题
  • 按照用途将代码进行分类 (将一组相干的业务逻辑归置到了同一个副作用函数中)
  • 简化重复代码, 使组件内部代码更加清晰
import {
      useEffect } from "react";
import ReactDOM from 'react-dom';

function Api (props) {
       

  function scroller() {
     
    console.log('滚动了')
  }
  useEffect(() => {
     
    window.addEventListener('scroll', scroller)
    return () => {
     
      window.removeEventListener('scroll', scroller)
    }
  }, [])
  return <div>
    <button onClick={
      () => ReactDOM.unmountComponentAtNode(document.getElementById('root')) }>卸载组件</button>
  </div>
}
  1. 只有指定数据发生变化时触发effect
useEffect(() => {
     
  document.title = count
}, [count])
  1. useEffect 结合异步函数

useEffect中的参数函数不能是异步函数, 因为useEffect函数要返回清理资源的函数, 如果是异步函数就变成了返回Promise

useEffect(() => {
     
  (async () => {
     
      await axios.get()
  })()
})

2.5 useMemo()

useMemo 的行为类似Vue中的计算属性, 可以监测某个值的变化, 根据变化值计算新值.

useMemo 会缓存计算结果. 如果监测值没有发生变化, 即使组件重新渲染, 也不会重新计算. 此行为可以有助于避免在每个渲染上进行昂贵的计算.

import {
      useMemo } from "react";

const result = useMemo(() => {
     
  return count *2
}, [count])

2.6 memo 方法 (性能优化)

性能优化, 如果本组件中的数据没有发生变化, 阻止组件更新. 类似类组件中的 PureComponent 和 shouldComponentUpdate

会返回一个新的组件

import {
      memo } from "react";

const Counter = memo(function Count(){
     
  return <div></div>
})

export default Counter;

2.7 useCallback() 方法 (性能优化)

性能优化, 缓存函数, 使组件重新渲染时得到相同的函数实例. 防止组件因为函数实例不同而重新渲染

import {
      memo, useCallback, useState } from "react";

function Api () {
     
  const [count, setCount] = useState(0);
  const resetCount = useCallback( () => setCount(0), [setCount])
  return <div>
    <div>{
     count}</div>
    <button onClick={
      () => setCount(count+1) }> +1</button>
    <Test resetCount={
     resetCount}/>
  </div>
}

const Test = memo(function Test1(props){
     
  console.log('组件渲染了')
  return <div>
    Test
    <button onClick={
      props.resetCount }> reset </button>
  </div>
})  

2.8 useRef()

  1. 获取DOM元素对象
import {
      useRef } from "react";
function TextInputWithFocusButton() {
     
  const inputEl = useRef(null);
  const onButtonClick = () => {
     
    // `current` 指向已挂载到 DOM 上的文本输入元素
    inputEl.current.focus();
  };
  return (
    <div>
      <input ref={
     inputEl} type="text" />
      <button onClick={
     onButtonClick}>Focus the input</button>
    </div>
  );
}
  1. 保存数据 (跨组件周期)

即使组件重新渲染, 保存的数据仍然还在. useFef保存的数据被更改不会触发组件重新渲染. 举例:可以用于清除定时器

function App() {
     
  let timer = useRef();
  useEffect(() => {
     
    timer = setInterval(() => {
     
      setCount(count + 1)
    },1000)
  })
  const stopCount = () => {
     
    clearInterval(timer)
  }
  return <div></div>
}

3. 自定义 Hook

  • 自定义 Hook 是标准的封装和共享逻辑的方式.
  • 自定义 Hook 是一个函数, 其名称以 use 开头.
  • 自定义 Hook 其实就是逻辑和内置 Hook 的组合.

主要目的就为了实现,组件之间的数据共享

import {
      useState, useEffect } from 'react';
// 自定义Hook
function useFriendStatus() {
       
  const [list, setList] = useState({
     });
  useEffect(() => {
     
    axios.get('http://xxx').then(res => setList(res.data))
  }, []);
  return [list, setList];
}
function App() {
       
  const [list, setList] = useStatus();
  return <div> {
     list} </div>
}

4. React 路由 Hooks

react-router-dom 路由提供的钩子函数

import {
      
  useHistory, 
  useLocation,
  useRourteMatch,
  useParams
} from 'react-router-dom'
// 获取对应的路由对象

5.useState 钩子函数简单实现

import React from 'react';
import ReactDOM from 'react-dom';

let state = [];
let setters = [];
let stateIndex = 0;

function createSetter (index) {
     
  return function (newState) {
     
    state[index] = newState;
    render ();
  }
}

function useState (initialState) {
     
  state[stateIndex] = state[stateIndex] ? state[stateIndex] : initialState;
  setters.push(createSetter(stateIndex));
  let value = state[stateIndex];
  let setter = setters[stateIndex];
  stateIndex++;
  return [value, setter];
}

function render () {
     
  stateIndex = 0;
  effectIndex = 0;
  ReactDOM.render(<App />, document.getElementById('root'));
}
function App() {
     
  const [count, setCount] = useState(0);
  const [name, setName] = useState('Tom');
  return <div>
    {
     count}
    <button onClick={
      () => setCount(count + 1) }>+1</button>
    <button onClick={
      () => setName('JDAK')}>名字</button>
  </div>;
}

6.useEffect 钩子函数简单实现

function render () {
     
  effectIndex = 0;
  ReactDOM.render(<App />, document.getElementById('root'));
}


let prevDepsAry = [];
let effectIndex = 0;

function useEffect(callback, depsAry) {
     
  // 判断callback是不是函数
  if (Object.prototype.toString.call(callback) !== '[object Function]') throw new Error('useEffect函数的第一个参数必须是函数');
  // 判断depsAry有没有被传递
  if (typeof depsAry === 'undefined') {
     
    // 没有传递
    callback();
  } else {
     
    // 判断depsAry是不是数组
    if (Object.prototype.toString.call(depsAry) !== '[object Array]') throw new Error('useEffect函数的第二个参数必须是数组');
    // 获取上一次的状态值
    let prevDeps = prevDepsAry[effectIndex];
    // 将当前的依赖值和上一次的依赖值做对比 如果有变化 调用callback
    let hasChanged = prevDeps ? depsAry.every((dep, index) => dep === prevDeps[index]) === false : true;
    // 判断值是否有变化
    if (hasChanged) {
     
      callback();
    }
    // 同步依赖值
    prevDepsAry[effectIndex] = depsAry;
    effectIndex++;
  }
}

7. useReducer 钩子函数简单实现

function useReducer (reducer, initialState) {
     
  const [state, setState] = useState(initialState);
  function dispatch (action) {
     
    const newState = reducer(state, action);
    setState(newState);
  }
  return [state, dispatch];
}

function App() {
     
  function reducer (state, action) {
     
    switch (action.type) {
     
      case 'increment':
        return state + 1;
      case 'decrement':
        return state - 1;
      default:
        return state;
    }
  }
  const [count, dispatch] = useReducer(reducer, 0);
  return <div>
    {
     count}
    <button onClick={
     () => dispatch({
     type: 'increment'})}>+1</button>
    <button onClick={
     () => dispatch({
     type: 'decrement'})}>-1</button>
  </div>;
}

React 之 Fomik

1.1 Formik 介绍

增强表单处理能力. 简化表单处理流程.
https://jaredpalmer.com/formik/

2 Formik 基本使用

官网:
https://github.com/jquense/yup#readme

下载

npm install formik

2.1 使用 formik 进行表单数据绑定以及表单提交处理.

import {
      useFormik } from 'formik';

function App () {
     
  const formik = useFormik ({
     initialvalues: {
      username: '张爽'}, onsubmit: values => {
     }});
  return <form onSubmit={
     formik.handleSubmit}>
    <input type="text" name="username"
      value={
     formik.values.username}
      onchange={
     formik.handleChange}/>
    <input type="submit"/>
  </form>
}

2.2 表单验证

function App () {
     
  const formik = useFormik ({
     
    validate: values => {
     
      const errors = {
     };
      if(!values.username) errors.username = '请用户输死';
      return errors;
    }, 
    onSubmit: values => {
     }
  });
  return <form onSubmit={
     formik.handleSubmit}>
    <div>{
     formik.touched.username && formik.errors.username ? formik.errors.username : ''}</div>
  </form>
}
// formik.handleBlur 离开焦点时触发验证
// onBlur={formik.handleBlur}
// formik.touched.username 判断表单元素是否被改动过

2.3 使用 yup 配合formik 表单验证

下载yup
npm install yup
使用

import {
      useFormik } from "formik";
import * as Yup from "yup";

const formik = useFormik ({
     
    initialvalues: {
      username: '张爽', password: 1234}, 
    validationSchema: Yup.object({
     
	    username: Yup.string()
	      .max(15, "用户名的长度不能大于15")
	      .required("请输入用户名"),
	   	password: Yup.string()
	   	  .max(8, "密码。。。")
	   	  .required("请输入密码")
	}),
    onSubmit: values => {
     }
});

2.4 getFieldProps 方法

减少样板代码

{
     ...formik.getFieldProps('username')} 
可以代替
onchange={
     formik.handleChange}
onBlur={
     formik.handleBlur}
value={
     formik.values.username}

2.5 使用组件的方式构建表单

组价

import {
      Formik, Form, Field, ErrorMessage, useField } from "formik";
import * as Yup from "yup";

function App() {
     
  const initialValues = {
     username: '', hobbies: ['足球', '篮球']};
  const handleSubmit = (values) => {
     
    console.log(values);
  };
  const schema = Yup.object({
     
    username: Yup.string()
      .max(15, "用户名的长度不能大于15")
      .required("请输入用户名"),
  });
  return (
    <Formik
      initialValues={
     initialValues}
      onSubmit={
     handleSubmit}
      validationSchema={
     schema}
    >
      <Form>
        <Field name="username" /> //默认是输入框
        <ErrorMessage name="username" />
        <Checkbox value="足球" label="足球" name="hobbies"/>
        <button type="submit">提交</button>
      </Form>
    </Formik>
  );
}

2.6 构建其他表单项

默认情况下, Field组件渲染的是文本框. 如要生成其他表单元素可以使用以下语法.

<Field name="username" as="textarea" /> // 文本域
<Field name="subject" as="select"> // 下拉框
	<option value="1">123</option>
	<option value="2">234</option>
	<option value="3">345</option>
</Field>

2.7 使用 useField 构建 自定义表单控件

import {
      useField } from "formik";

function myInput({
     label, ...props}) {
     
	const [field, meta] = useField(props)
	return <div>
		<lable htmlFor={
     props.id}>{
      label }</label>
		<input {
     ...field} {
     ...props}/>
		{
     meta.touched && meta.error ? <div>meta.error</div> : null}
	</div>
}
<myInput id="user" label="密码" type="text" name="username" placeholder="请输入用户名"/>

受控组件与非受控组件

非受控组件

表单数据交由DOM节点管理. 特点是表单数据在需要时进行获取. 代码实现相对简单.

受控组件

表单数据交由state对象管理. 特点是可以实时得到表单数据. 代码相对复杂.

推荐使用受控组件

CSS-IN-JS

集成 CSS 代码在 JavaScript 文件

1. 为什么会有 CSS-IN-JS

CSS-IN-JS 是 WEB 项目中将 CSS 代码捆绑在 JavaScript 代码中的解决方案.

这种方案旨在解决 CSS 的局限性, 例如缺乏动态功能, 作用域和可移植性.
将css与js放在一起,方便组件移植,并且让其有自己的作用域,与VUE 中的 style 中的 scoped 作用一样。

2. CSS-IN-JS 方案的优缺点

优点:

  1. 让 CSS 代码拥有独立的作用域, 阻止 CSS 代码泄露到组件外部, 防止样式冲突.
  2. 让组件更具可移植性, 实现开箱即用, 轻松创建松耦合的应用程序
  3. 让组件更具可重用性, 只需编写一次即可, 可以在任何地方运行. 不仅可以在同一应用程序中重用组件, 而且可以在使 用相同框架构建的其他应用程序中重用组件.
  4. 让样式具有动态功能, 可以将复杂的逻辑应用于样式规则, 如果要创建需要动态功能的复杂UI, 它是理想的解决方案.

缺点:

  1. 为项目增加了额外的复杂性.
  2. 自动生成的选择器大大降低了代码的可读性

推荐使用CSS-IN-JS方案

3. Emotion 库

Emotion 是一个旨在使用 JavaScript 编写 CSS 样式的库. 实现 CSS-IN-JS 方案

3.1下载

npm install @emotion/core @emotion/styled

3.2使用方式

1、JSX Pragma

通知 babel, 不再需要将 jsx 语法转换为 React.createElement 方法, 而是需要转换为 jsx 方法.

React 之 专题(React Hooks、Fomik、CSS-IN-JS、Chakra-UI )_第1张图片

/** @jsx jsx **/  //注释也要写
import {
      jsx } from '@emotion/core';

function App() {
     
	return <div css={
     {
      width: 200, height: 200 }}>lalal</div>
}

2、 Babel Preset

  1. npm run eject 使用其弹窗 react 配置
  2. 在 package.json 文件中找到 babel 属性, 加入如下内容
"presets":[
	"react-app",
	"@emotion/babel-preset-css-prop"
]

之后便可在组件中直接使用css={}属性
推荐使用第二种方式

3.3 css方法

import {
      css } from '@emotion/core';
// 方式1 推荐
const style = css`
	width: 100px;
	background: skyblue;
`;
// 方式2
style = css({
     
	width: 100,
	background: 'skyblue'
})

<div css={
     style}> App </div>

3.4 css 属性优先级

props 对象中的 css 属性优先级高于组件内部的 css 属性.
在调用组件时可以在覆盖组件默认样式.

及外部优先级大于内部的

3.5 Styled Components 样式化组件

样式化组件就是用来构建用户界面的,是 emotion 库提供的另一种为元素添加样式的方式。

3.5.1 创建样式化组件

用法

import {
      styled } from '@emotion/styled';

const Conter = styled.div`  //也可使用对象形式
  width: 100px;
  height: 100px;
`;

function App() {
     
  return <div>
  	App works
  	<Conter/>
  </div>;
}

3.5.2 根据 props 属性覆盖样式

import {
      styled } from '@emotion/styled';

const Conter = styled.div`  //也可使用对象形式
  width: ${
       props => props.width || '100px'};
  height: 100px;
`;
// ----------------------
const Conter = styled.div(props => ({
       //对象形式
  width: props && props.width || '100px',
  height: '100px'
)});


function App() {
     
  return <div>
  	App works
  	<Conter width={
     100}/>
  </div>;
}

3.5.3 为任何组件添加样式

import {
      styled } from '@emotion/styled';

function Demo ({
     className}) {
     
	return <div className={
     className}>Demo</div>
}

const Conter = styled(Demo)`
  width: 100px;
  height: 100px;
  color: red;
`;

function App() {
     
  return <div>
  	<Conter/>
  </div>;
}

3.5.4 通过父组件设置子组件样式

React 之 专题(React Hooks、Fomik、CSS-IN-JS、Chakra-UI )_第2张图片 或者 React 之 专题(React Hooks、Fomik、CSS-IN-JS、Chakra-UI )_第3张图片

如果不生效 (需要 babel 插件支持)
babel 插件配置

  1. npm install babel-plugin-emotion
  2. 在 package.json 文件中找到 babel 属性, 加入如下内容:
"babel": {
     
	"plugins": ["emotion"]
}

3.5.5 嵌套选择器 &

& 表示组件本身.

React 之 专题(React Hooks、Fomik、CSS-IN-JS、Chakra-UI )_第4张图片

3.5.6 as 属性

要使用组件中的样式, 但要更改呈现的元素, 可以使用 as 属性.

React 之 专题(React Hooks、Fomik、CSS-IN-JS、Chakra-UI )_第5张图片

as 可以改变组件的标签;

3.6 样式组合

React 之 专题(React Hooks、Fomik、CSS-IN-JS、Chakra-UI )_第6张图片

在样式组合中, 后调用的样式优先级高于先调用的样式. 后覆盖前的;

3.7 全局样式

React 之 专题(React Hooks、Fomik、CSS-IN-JS、Chakra-UI )_第7张图片

引入 Global 组件

3.8 关键帧动画

引入 keyframes 组件

import {
      css, keyframes } from '@emotion/core';
React 之 专题(React Hooks、Fomik、CSS-IN-JS、Chakra-UI )_第8张图片

3.9 主题

  1. 下载主题模块
    npm install emotion-theming
  2. 使用
// index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
// 引入 ThemeProvider 组件
import {
      ThemeProvider } from 'emotion-theming';
// 主题
const theme = {
     
  colors: {
     
    primary: 'tomato'
  }
};

ReactDOM.render(
  // 将 ThemeProvider 放置在视图在最外层
  <ThemeProvider theme={
     theme}><App /></ThemeProvider>,
  document.getElementById('root')
);
// app.js
import React from 'react';
import {
      css, keyframes } from '@emotion/core';
import {
      styled } from '@emotion/styled';
import {
      useTheme } from 'emotion-theming';
// 获取主题
const primaryColor = props => css`
  color: ${
       props.colors.primary}
`

function App() {
     
  console.log(useTheme()); // 获取主题

  return <div css={
     primaryColor}>
    App works
    <Conter/>
  </div>;
}

export default App;

Chakra-UI

现代化 React UI 框架 Chakra-UI

1. Chakra-UI 介绍

Chakra UI 是一个简单的, 模块化的易于理解的 UI 组件库. 提供了丰富的构建 React 应用所需的UI组件.
文档:
https://next.chakra-ui.com/docs/getting-started
https://chakra-ui.com/docs/getting-started

  1. Chakra UI 内置 Emotion,是 CSS-IN-JS 解决方案的集大成者
  2. 基于 Styled-Systems https://styled-system.com/
  3. 支持开箱即用的主题功能
  4. 默认支持白天和黑夜两种模式
  5. 拥有大量功能丰富且非常有用的组件
  6. 使响应式设计变得轻而易举
  7. 文档清晰而全面. 查找API更加容易
  8. 适用于构建用于展示的给用户的界面
  9. 框架正在变得越来越完善

2. Chakra-UI 开始

2.1 下载 chakra-ui

npm install @chakra-ui/[email protected]

2.2 克隆默认主题

Chakra-UI 提供的组件是建立在主题基础之上的, 只有先引入了主题组件才能够使用其他组件.
npm install @chakra-ui/theme

2.3使用

引入

import React from "react";
import ReactDOM from "react-dom";
import App from "./components/App";
import {
      ChakraProvider, CSSReset } from "@chakra-ui/core"; // css重置组件
import theme from '@chakra-ui/theme'; // 主题

ReactDOM.render(
  <ChakraProvider theme={
     theme}>
    <CSSReset />
    <App />
  </ChakraProvider>,
  document.getElementById("root")
);

3. 主题

3.1 颜色模式(color mode)

chakra-ui 提供的组件都支持两种颜色模式, 浅色模式(light)和暗色模式(dark). 可以通过 useColorMode 进行颜色模式的更改.

React 之 专题(React Hooks、Fomik、CSS-IN-JS、Chakra-UI )_第9张图片

Chakra 将颜色模式存储在 localStorage 中, 并使用类名策略来确保颜色模式是持久的.

3.2 根据颜色模式设置样式

chakra 允许在为元素设置样式时根据颜色模式产生不同值. 通过 useColorModeValue 钩子函数实现.

React 之 专题(React Hooks、Fomik、CSS-IN-JS、Chakra-UI )_第10张图片

3.3 强制组件颜色模式

使组件不受颜色模式的影响, 始终保持在某个颜色模式下的样式.

React 之 专题(React Hooks、Fomik、CSS-IN-JS、Chakra-UI )_第11张图片

3.4 颜色模式通用设置

  1. 设置默认颜色模式

通过 theme.config.initialColorMode 可以设置应用使用的默认主题.

  1. 使用操作系统所使用的颜色模式

通过 theme.config.useSystemColorMode 可以设置将应用的颜色模式设置为操作系统所使用的颜色模式.

3.5 主题对象

Colors

在设置颜色时, 可以但不限于取主题中提供的颜色值.

React 之 专题(React Hooks、Fomik、CSS-IN-JS、Chakra-UI )_第12张图片
<Box color="red.500">Box>

Space

使用 space 可以自定义项目间距. 这些间距值可以由 padding, margin 和 top, left, right, bottom 样式引用.

<Box mb="5">Box> 

Sizes

使用 size 可以自定义元素大小, 这些值可以由 width, height 和 maxWidth, minWidth 等样式引用.

<Box w="lg">Box> 

Breakpoints

配置响应数组值中使用的默认断点. 这些值将用于生成移动优先(即最小宽度)的媒体查询.

// theme.js
import {
      createBreakpoints } from "@chakra-ui/theme-tools"

export default createBreakpoints({
     
  sm: "30em",
  md: "48em",
  lg: "62em",
  xl: "80em",
  "2xl": "96em",
})
<Box fontSize={
     ["sm", "md", "lg", "xl"]}>Font Size</Box>

React Icons 推荐

官网:
http://react-icons.github.io/react-icons/

你可能感兴趣的:(笔记,react)