本文主要是介绍ReactJs笔记摘录,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
文章目录
- 前言
- 目录结构
- Hook函数
- useState
- useEffect
- useContext
- useReducer
- useCallback
- useMemo
- JSX语法
- 根元素与斜杠
- 使用变量
- 推荐使用className替代class
- antd和tailwindcss
- 组件通信
- 父传子:props和自定义函数事件
- 子传父:props.onchange
- Context
- 状态管理
- 结合useContext()和useReducer()实现全局状态共享
- UI 问题
- 选择哪个UI框架?
- 编程规范
- 参考链接
- React使用
- UI框架
- 组件
前言
以前2018年搞过一段时间react + antd开发,兜兜转转又回到react世界。本文力图记录一些易忘易混的知识点。
目录结构
├─package-lock.json
├─package.json ------------ // 项目配置
├─postcss.config.js ------- // postcss 配置
├─public ------------------ // 公开目录
│ ├─favicon.ico
│ └─index.html
├─README.md ---------- // 项目说明
└─src --------------------- // 源码目录
├─App.tsx --------------- // 根组件
├─assets ---------------- // 静态资源目录
│ └─images -------------- // 图片目录
│ └─logo.png ------ // logo 图片
│ └─svg -------------- // 图标目录
│ └─logo.svg ------ // logo 图片
├─components ------------ // 公共组件目录
│ └─Menu ---------------- // 公共组件
│ ├─index.tsx ---------- // 组件文件
│ └─index.scss ------ // 组件样式
├─constants ---------------- // 项目常量
│ └─index.ts
├─libs ------------------ // 第三方库目录
├─index.tsx --------------- // 主入口
├─router ---------------- // 路由配置
│ └─index.tsx
├─store ----------------- // 状态管理
│ ├─module.ts // 模块
│ └─index.ts // 入口
├─tests ----------------- // 测试目录
├─utils ----------------- // 工具目录
│ ├─a.ts
│ └─index.ts
└─pages ----------------- // 视图目录└─Home ---------------- // 页面组件├─components -------- // 子组件目录│ └─Header│ ├─index.tsx│ └─index.scss└─index.tsx ---------- // 组件主体
Hook函数
Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。它们可以帮助我们简化组件的代码并提高代码的可维护性。
Hook 本质就是 JavaScript 函数,但是在使用它时需要遵循两条规则。react官方提供了一个 linter 插件来强制执行这些规则。
- 只在最顶层使用 Hook。不要在循环,条件或嵌套函数中调用 Hook, 确保总是在你的 React 函数的最顶层调用他们。
- 只在 React 函数组件中调用 Hook,也可以在自定义 Hook 中调用其他 Hook。但不要在普通的 JavaScript 函数中调用 Hook。
以下是常见的 Hook 函数:
useState
useState 是一个用于在函数组件中添加状态的 Hook 函数。它接受一个初始状态值,并返回一个数组,其中第一个值为当前状态值,第二个值为更新状态的函数。
import React, { useState } from 'react';function Example() {const [count, setCount] = useState(0);return (<div><p>You clicked {count} times</p><button onClick={() => setCount(count + 1)}>Click me</button></div>);
}
useEffect
useEffect 是一个用于在函数组件中添加副作用的 Hook 函数。它接受一个回调函数和一个依赖数组作为参数。回调函数在组件挂载、更新或卸载时执行。依赖数组中的值发生变化时,也会重新执行回调函数。
import React, { useState, useEffect } from 'react';function Example() {const [count, setCount] = useState(0);useEffect(() => {document.title = `You clicked ${count} times`;}, [count]);return (<div><p>You clicked {count} times</p><button onClick={() => setCount(count + 1)}>Click me</button></div>);
}
useContext
useContext 是一个用于在函数组件中使用 React Context 的 Hook 函数。它接受一个 Context 对象作为参数,并返回该上下文的当前值。
import React, { createContext, useContext } from 'react';const ThemeContext = createContext('light');function Example() {return (<ThemeContext.Provider value="dark"><p>Current theme: {useContext(ThemeContext)}</p></ThemeContext.Provider>);
}
useReducer
useReducer 是一个用于在函数组件中使用状态 reducer 的 Hook 函数。它接受一个 reducer 函数和一个初始状态值作为参数,并返回一个数组,其中第一个值为当前状态值,第二个值为更新状态的函数。
import React, { useReducer } from 'react';function App() {const [state, dispatch] = useReducer(reducer, initialState);return (<div><p>Current state: {state}</p></div>);
}function reducer(state, action) {switch (action.type) {case 'increment':return state + 1;case 'decrement':return state - 1;default:throw new Error();}
}
useCallback
useCallback 是一个用于在函数组件中缓存函数的 Hook 函数。它接受一个函数作为参数,并返回一个缓存函数。如果传入的函数没有发生变化,则返回上次缓存的结果;否则,会重新创建一个新的缓存函数。
import React, { useState, useCallback } from 'react';function Example() {const [count, setCount] = useState(0);const handleClick = useCallback(() => {setCount(count + 1);}, [count]);return (<div><p>You clicked {count} times</p><button onClick={handleClick}>Click me</button></div>);
}
useMemo
useMemo 是一个用于在函数组件中缓存计算结果的 Hook 函数。它接受一个函数作为参数,并返回缓存的结果。如果传入的函数没有发生变化,则返回上次缓存的结果;否则,会重新计算新的结果。
import React, { useState, useMemo } from 'react';function Example() {const [count, setCount] = useState(0);const doubleCount = useMem
JSX语法
根元素与斜杠
注意局部的jsx片段也要加根元素:
return (<div>{items.map((item) => (// 此处只能有一个根元素!!!<>...<div className="flex min-w-fit min-h-fit h-24 w-24 border-4 rounded-md bg-white-100 justify-center">// img后要加斜杠<img loading="lazy" src="http://www.icoolcms.com/cms/link/logo/2384"/></div></>))}</div>
)
使用变量
<img className="logoImg" loading="lazy" src={`http://www.icoolcms.com/cms/link/logo/${item.linkId}`}/>
推荐使用className替代class
className属性是React中使用的属性名称,用于避免与JavaScript的保留关键字class冲突。
antd和tailwindcss
可以在Antd组件中直接使用Tailwindcss类:
<Button className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">Click me
</Button>
组件通信
React 最推荐的数据交互方式是:props & onChnage。在这种交互方式里:对于一个可视组件 ComponentA,用 props 来向它发送信息,而用 onChange 回调函数来接收 ComponentA 发送的信息。在程序世界里,我们更喜欢把上述「交互方式」称为「接口」,虽然这个「接口」不是我们在面向对象语言里的 interface,但是跟 interface 有着类似的功能。
父传子:props和自定义函数事件
// 父组件
function Money() {const [selected, setSelected] = useState('food');return (<TagsSection value={selected}/>);
}// 子组件
type Props = {//声明props的数据类型value: string;
}const TagsSection: React.FC<Props> = (props) => {const tagName = props.value;return (<div>the tag name is { tagName }</div>);
};
子传父:props.onchange
import React, { useState } from "react";const MyComponent = ({ onChange, initialValue }) => {const [value, setValue] = useState(initialValue);const handleChange = (event) => {setValue(event.target.value);onChange(event.target.value);};return (<inputtype="text"value={value}onChange={handleChange}/>);
};const App = () => {const handleValueChange = (value) => {console.log(`Value changed to: ${value}`);};return (<MyComponent onChange={handleValueChange} initialValue="Initial value" />);
};export default App;
在这个示例中,我们定义了一个名为MyComponent的React组件,它接受一个onChange属性和一个initialValue属性。onChange属性定义了当组件的值发生变化时应该调用的函数,而initialValue属性则定义了组件的初始值。
在MyComponent组件内部,我们使用useState Hook来存储组件的值。然后,我们定义了一个handleChange函数,该函数在用户输入发生变化时被调用。在这个函数中,我们调用setValue来更新组件的值,并调用onChange函数来通知父组件值已更改。
最后,我们定义了一个App组件,该组件使用MyComponent组件,并将handleValueChange函数作为onChange属性的值传递。当组件的值发生变化时,handleValueChange函数将被调用,并输出新的值。
Context
Context 的使用方式:
- 使用 const xxx = createContext(null) 创建上下文
- 使用 <xxx.Provider> 圈定作用域
- 在作用域内使用 useContext(xxx) 来使用上下文
先创建一个 Context 对象:
import React from "react";const ThemeContext = React.createContext();export default ThemeContext;
再创建Provider:
import React from "react";
import ThemeContext from "./ThemeContext";const ThemeProvider = ({ theme }) => {return (<ThemeContext.Provider value={theme}>{/* 这里可以传递其他内容 */}</ThemeContext.Provider>);
};export default ThemeProvider;
再创建Consumer, 它将使用 ThemeContext 上下文来获取 theme 数据
import React from "react";
import ThemeContext from "./ThemeContext";const ThemeConsumer = ({ children }) => {return (<ThemeContext.Consumer>{theme => {// 在这里可以使用 theme 数据return <>{children}</>;}}</ThemeContext.Consumer>);
};export default ThemeConsumer;
连起来:
import React from "react";
import ThemeProvider from "./ThemeProvider";
import ThemeConsumer from "./ThemeConsumer";const theme = {color: "blue",
};const App = () => {return (<ThemeProvider theme={theme}><ThemeConsumer>{({ theme }) => (<div><h1>Theme color: {theme.color}</h1></div>)}</ThemeConsumer></ThemeProvider>);
};export default App;
在这个示例中,我们首先创建了一个 ThemeContext 对象,然后创建了一个 ThemeProvider 组件,它将提供 theme 数据。接下来,我们创建了一个 ThemeConsumer 组件,它将使用 ThemeContext 上下文来获取 theme 数据。最后,我们创建了一个 Root 组件,它将使用 ThemeProvider 组件提供 theme 数据,并使用 ThemeConsumer 组件来获取 theme 数据。
如果不用Consumer,也可以直接使用useContext()获得context数据:
// 使用useContext Hook
const { isLoggedIn, login, logout } = useContext(AuthContext);
状态管理
业内常规的成熟方案一般有:mobx、redux等专门的全局状态管理库,相对而言基本可以覆盖支持所有的复杂业务场景,再也就简单粗暴通过多个Context嵌套来实现共享。Redux 是借鉴 Flux 开发的,它们都是单向数据流,而 MobX 则有所不同,它是基于观察者模式实现。
React18以后的版本内置了useReducer() hook,它是 useState() 的替代品,简单的状态可以直接使用 useState,当我们遇到复杂多层级的状态或者下个状态要依赖上个状态时使用 useReducer() 则非常方便,在配合 Context 与 useContext() 就能实现类似 Redux 库的功能。
- 当我们项目中复杂程度较低时,建议只用state就可以了
- 如果仅仅因为存在多层传递数据的场景,不建议使用mobx或redux,可使用context解决
- 如果仅仅因为夸路由数据共享,不建议使用mobx或redux,可使用context或者路由传参解决
- 如果业务复杂,需要使用第三方状态管理解决复杂度,看下一条
- 当项目复杂度一般,小规模团队或开发周期较短、要求快速上线时,推荐使用mobx
- 当项目复杂度较高,团队规模较大或要求对事件分发处理可监控可回溯时,推荐使用redux,可尝试使用 rematch或@reduxjs/toolkit,减少模板代码
结合useContext()和useReducer()实现全局状态共享
写一个store.tsx:
import React, { createContext, useReducer, useContext } from 'react';const initialState = { count: 0 };function reducer(state, action) {switch (action.type) {case 'increment':return { count: state.count + 1 };case 'decrement':return { count: state.count - 1 };default:throw new Error();}
}const StateContext = createContext();
const DispatchContext = createContext();function useStateStore() {return useContext(StateContext);
}function useDispatchStore() {return useContext(DispatchContext);
}function StoreProvider({ children }) {const [state, dispatch] = useReducer(reducer, initialState);return (<StateContext.Provider value={state}><DispatchContext.Provider value={dispatch}>{children}</DispatchContext.Provider></StateContext.Provider>);
}export { useStateStore, useDispatchStore, StoreProvider };
修改状态:
import React from 'react';import { useDispatchStore } from './store';function Producer() {const dispatch = useDispatchStore();console.log('header udpate');return (<><button onClick={() => dispatch({type: 'decrement'})}>-</button><button onClick={() => dispatch({type: 'increment'})}>+</button></>);}export default Producer;
消费状态:
import React from 'react';import { useStateStore } from './store';function Footer() {const state = useStateStore();console.log('footer udpate');return (<p>{state.count}</p>);}export default Footer;
UI 问题
选择哪个UI框架?
除了大名鼎鼎的antd之外,其实还有很多选择。react-bootstrap也是堂堂正正,大部分UI组件都不错。daisyui也冉冉升起。
编程规范
- 命名:props、变量用小驼峰,组件的文件名用大驼峰
- 引号:JSX 属性中用双引号("),但是在js里用单引号(')
- 自闭合标签:在自闭和标签内空一格,如<Foo />,当没有子元素时,最好用自闭合标签
- 推荐用 ref callback 函数
useRef() 返回一个具有单个 current 属性 的 ref 对象,并初始化为你提供的初始值
// bad
<Fooref="myRef"
/>// good
<Fooref={(ref) => { this.myRef = ref; }}
/>
- 用箭头函数关闭局部变量
- 构造函数里绑定事件处理函数
- 不要在 React 组件里使用下划线作为内部方法名前缀
参考链接
React使用
- use-context-selector: 通过选择需要的状态从而规避掉无关的状态改变时带来的渲染开销
- 如何优雅地使用React Context
UI框架
- Ant Design: 88k stars,可惜不是基于tailwindcss的。
- react-bootstrap
- daisyui: 27k stars
- material-ui
- shadcn
- hyperui
- flowbite
Build websites even faster with components on top of Tailwind CSS,Start developing with an open-source library of over 600+ UI components, sections, and pages built with the utility classes from Tailwind CSS and designed in Figma. - primefaces
- preline: Preline UI is an open-source set of prebuilt UI components based on the utility-first Tailwind CSS framework.
- 基于Tailwindcss的headlessui
- Evergreen Segment
- Blueprint React UI
- Material Design for Bootstrap v5 & v4: Top quality open-source UI Kits
- Grommet
- visx
- Chakra
- React-admin
About A frontend Framework for building data-driven applications running on top of REST/GraphQL APIs, using TypeScript, React and Material Design - Semantic UI React
- nextui: Beautiful, fast and modern React UI library.
- fluent2
- retool: 要收费
- React Redux
组件
- multilevel-dropdown
- how-create-multilevel-dropdown-menu
这篇关于ReactJs笔记摘录的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!