Reactjs常用组件

news/2024/5/13 2:27:12

1 react

1.1 useState

让函数组件具有维持状态的能力

const[count, setCount]=useState(0);

1.2 useEffect

执行副作用,useEffect 的第二个参数告诉 React 用到了哪些外部变量

类似于Vue watch的作用

useEffect(fn, deps);

1.每次 render 后执行:不提供第二个依赖项参数。

比如useEffect(() => {})。

2.仅第一次 render 后执行:提供一个空数组作为依赖项。

比如useEffect(() => {}, [])。

3.第一次以及依赖项发生变化后执行:提供依赖项数组。

比如useEffect(() => {}, [deps])。

4.组件 unmount 后执行:返回一个回调函数。

比如useEffect() => { return () => {} }, [])。
useEffect(() => {document.title = "Hello, " + name;
}, [name]);

1.3 useCallback

缓存回调函数。

useCallback(fn, deps)

useCallback是React Hooks中的一个函数,用于优化函数组件的性能。它的作用是返回一个memoized(记忆化的)函数,这个函数只有在依赖项发生变化时才会重新计算,否则会直接返回上一次计算的结果。 

例子:

import React, { useState, useCallback } from 'react';function Counter() {const [count, setCount] = useState(0);const handleIncrement = useCallback(() => setCount(count + 1),[count], // 只有当 count 发生变化时,才会重新创建回调函数);return <button onClick={handleIncrement}>+</button>
}

例子2:

import { useState, useCallback } from 'react';function MyComponent(props) {const [count, setCount] = useState(0);const handleClick = useCallback(() => {console.log(`Clicked ${count} times`);}, [count]);return (<><div>Count: {count}</div><button onClick={() => setCount(count + 1)}>Increment</button><button onClick={handleClick}>Click me</button></>);
}

1.4 useMemo

缓存计算的结果,类似于Vue中computed的作用

useMemo(fn, deps);

1.5 useRef

在多次渲染之间共享数据

const myRefContainer =useRef(initialValue);

1.6 useContext

定义全局状态

很多状态管理框架,比如 Redux,正是利用了 Context 的机制来提供一种更加可控的组件之间的状态管理机制。

1.7 createRef

创建一个 React ref 对象

import React, { createRef } from 'react';class MyComponent extends React.Component {constructor(props) {super(props);// 创建一个 ref 对象this.myRef = createRef();}render() {return (<div>{/* 将 ref 对象附加到一个 DOM 元素上 */}<input type="text" ref={this.myRef} /></div>);}
}

1.8 memo

React.memo 是 React 提供的一个高阶组件(Higher-Order Component),用于优化函数组件的性能。它类似于类组件中的 shouldComponentUpdate 方法,用于在 props 发生变化时判断是否重新渲染组件。

import React from 'react';const MyComponent = React.memo((props) => {// 在这里定义组件逻辑return (<div>{/* 使用 props 中的数据渲染组件 */}<h1>{props.title}</h1><p>{props.content}</p></div>);
});

1.9 组件创建

const ImgUpload: FC<IProps> = (props: IProps): ReactElement => {return (<div></div>)
};
export default memo(ImgUpload);

1.10 Suspense

就是一种加载组件优化,提升用户体验。

children:真正的 UI 渲染内容。

fallback:真正的 UI 未渲染完成时代替其渲染的备用 UI,它可以是任何有效的 React 节点。

import { Suspense } from 'react';
<Suspense fallback={<Loading />}><SomeComponent />
</Suspense>

2 Redux Toolkit

2.1 createSlice

接受初始状态的函数、reducer 函数的对象和“切片名称”, 并自动生成与 reducer 和 state 相对应的动作创建者和动作类型。类似于 Vue 中 Vuex 中的 store

function createSlice({//此状态切片的字符串名称。生成的操作类型常量将使用此作为前缀。name: string,// 此状态切片的初始状态值。initialState: State,//一个包含 Redux “case reducer” 函数的对象reducers: Record<string, ReducerFunction | ReducerAndPrepareObject>,// A "builder callback" function used to add more reducersextraReducers?: (builder: ActionReducerMapBuilder<State>) => void,// A preference for the slice reducer's location, used by `combineSlices` and `slice.selectors`. Defaults to `name`.reducerPath?: string,// An object of selectors, which receive the slice's state as their first parameter.selectors?: Record<string, (sliceState: State, ...args: any[]) => any>,
})

例子:

import { createSlice } from '@reduxjs/toolkit'const counterSlice = createSlice({name: 'counter',initialState: 0,reducers: {increment: (state) => state + 1,},
})

2.2 createAsyncThunk

一个接受 Redux 操作类型字符串的函数和一个应该返回 promise 的回调函数。通常用于处理异步逻辑。

// 创建一个异步的 Thunk action creator
export const getUserById = createAsyncThunk('user/getUserById', // 定义 action 的 typeasync (userId) => {// 异步逻辑,例如从服务器获取数据const response = await fetchUserById(userId);// 返回获取到的数据作为 action payloadreturn response.data;}
);

2.3 createAction

在 Redux 中定义动作的常用方法是分别声明一个动作类型常量和一个动作创建器函数来构造该类型的动作。与createAsyncThunk区别是:一个同步一个异步。

const INCREMENT = 'counter/increment'function increment(amount: number) {return {type: INCREMENT,payload: amount,}
}const action = increment(3)
// { type: 'counter/increment', payload: 3 }

2.4 createReducer

用于创建 Redux 中的 reducer

  • initialState :第一次调用 reducer 时应使用的初始状态。这也可能是一个“延迟初始值设定项”函数,该函数在调用时应返回初始状态值。每当调用 reducer with 作为其状态值时,都会使用它,并且主要用于从 中读取初始状态等情况。State | (() => State)undefinedlocalStorage
  • builder回调 接收要定义的构建器对象的回调 大小写缩减器通过调用 .(builder: Builder) => voidbuilder.addCase(actionCreatorOrType, reducer)
import { createReducer } from '@reduxjs/toolkit';// 定义初始状态
const initialState = {value: 0
};// 使用 createReducer 创建 reducer
const counterReducer = createReducer(initialState, {increment: (state) => {state.value += 1;},decrement: (state) => {state.value -= 1;},
});export default counterReducer;

3 react-redux

3.1 创建项目

npx create-react-app zhiqu-web-test --template typescript

3.2 useselector

共享状态,从Redux的store中提取数据(state)

const result: any = useSelector(selector: Function, equalityFn?: Function)

selector 在概念上大约等同于 mapStateToProps argument to connect。

selector 将以整个 Redux store state 作为唯一的参数被调用。每当函数组件渲染时,selector 就会被运行(除非在组件的前一次渲染后引用没有改变,这样 hooks 就会返回缓存的结果,而不是重新运行 selector)。useSelector() 也会订阅 Redux store,每当有 action 被 dispatched 时就会运行 selector。

全等比较和更新

默认的对比方式是严格的 === 引用比较

import { shallowEqual, useSelector } from 'react-redux'
const selectedData = useSelector(selectorReturningObject, shallowEqual)

 结合useEffect做全局的store监听:

const channel = useSelector<any, IChannel>((state) => {return state.channelReducer?.channel as IChannel;});
useEffect(() => {...}, [channel]);

3.3 configureStore

提供了一个简单而灵活的方式来创建 Redux store,使得 Redux 应用的设置过程更加轻松和高效。它是 Redux Toolkit 提供的一个重要工具,可以帮助开发者更快地搭建和管理 Redux 应用。

import { configureStore } from '@reduxjs/toolkit';
// ...const store = configureStore({reducer: {posts: postsReducer,comments: commentsReducer,users: usersReducer,},
});// 从 store 本身推断出 `RootState` 和 `AppDispatch` types
export type RootState = ReturnType<typeof store.getState>;
// 类型推断: {posts: PostsState, comments: CommentsState, users: UsersState}
export type AppDispatch = typeof store.dispatch;

综合案例:使用 createSlice、createAsyncThunk 和 configureStore 

import { configureStore, createSlice, createAsyncThunk } from '@reduxjs/toolkit';// 定义一个异步 Thunk action creator
const fetchUserById = createAsyncThunk('users/fetchById',async (userId, thunkAPI) => {const response = await fetch(`https://jsonplaceholder.typicode.com/users/${userId}`);return response.json();}
);// 定义一个初始状态
const initialState = {user: {},loading: false,error: null,
};// 创建一个 slice
const userSlice = createSlice({name: 'user',initialState,reducers: {changeUser(state, { payload }) {state.user= payload;},},extraReducers: (builder) => {builder.addCase(fetchUserById.pending, (state, action) => {state.loading = true;}).addCase(fetchUserById.fulfilled, (state, action) => {state.loading = false;state.user = action.payload;}).addCase(fetchUserById.rejected, (state, action) => {state.loading = false;state.error = action.error.message;});},
});// 导出 slice 中的 action creators
export const { changeUser } = userSlice.actions;// 创建 Redux store
const store = configureStore({reducer: userSlice.reducer,
});export default store;//将其分发到 Redux store 中。这样一来,Redux store 中的相应 reducer 将会根据'changeUser' //action 的类型来更新用户信息的状态。
store.dispatch(changeUser(user));import { type Dispatch } from 'redux';
dispatch(fetchUserById(userId));

在 Redux 应用中,store.dispatchdispatch 都用于触发 action,但它们的使用方式略有不同。

  1. store.dispatch: 用于分发 action 到 Redux store 中。它通常在组件外部被调用,比如在 Redux 相关的业务逻辑代码中或者 Redux 中间件中。示例:store.dispatch(action)

  2. dispatch: dispatch 是一个函数,通常通过 React Redux 提供的 useDispatch hook 或者 connect 函数的返回值来获取。它用于在 React 组件中分发 action。dispatch 函数本质上是 store.dispatch 的封装,用于在组件中直接触发 action,而不需要显式地引用 Redux store。示例:dispatch(action)

总的来说,store.dispatch 是 Redux store 实例的方法,用于在 Redux 应用的任意位置触发 action,而 dispatch 是一个函数,通常在 React 组件中使用,用于触发 action 并更新 Redux store 中的状态。

3.4 useDispatch 

const dispatch = useDispatch()

这个 hook 返回一个对 Redux store 中的 dispatch 函数的引用。dispatch结合store使用

import React from 'react'
import { useDispatch } from 'react-redux'export const CounterComponent = ({ value }) => {const dispatch = useDispatch()return (<div><span>{value}</span><button onClick={() => dispatch({ type: 'increment-counter' })}>Increment counter</button></div>)
}

3.5 useStore

为什么很少使用 useStore

  • 在 React Redux 中,useStore 允许你从默认的上下文中获取当前的 Redux store 实例。然而,它在实际开发中很少被使用,因为大多数情况下,我们不需要直接访问整个 store。
  • 使用 useStore 的主要原因是为了访问 store 的状态或执行一些自定义逻辑。但是,这通常不是最佳实践,因为 React Redux 提供了更高级的 API 来处理 store 交互,例如 useSelector 和 useDispatch
import React from 'react';
import { useStore } from 'react-redux';const MyComponent = () => {const store = useStore();const handleClick = () => {// 分发一个 action 到 Redux store 中store.dispatch({ type: 'SOME_ACTION' });// 获取当前 Redux store 中的状态const state = store.getState();console.log(state);};return (<button onClick={handleClick}>Dispatch Action</button>);
};export default MyComponent;

3.6 useselector

共享状态,从Redux的store中提取数据(state)

const result: any = useSelector(selector: Function, equalityFn?: Function)

selector 在概念上大约等同于 mapStateToProps argument to connect。

selector 将以整个 Redux store state 作为唯一的参数被调用。每当函数组件渲染时,selector 就会被运行(除非在组件的前一次渲染后引用没有改变,这样 hooks 就会返回缓存的结果,而不是重新运行 selector)。useSelector() 也会订阅 Redux store,每当有 action 被 dispatched 时就会运行 selector。

  const channel = useSelector<{ channelReducer: { channel: IChannel } }, IChannel>((state) => {return state.channelReducer.channel as IChannel;});

4 redux-immutable

4.1 combineReducers

组合reducer

import { combineReducers } from 'redux-immutable';
const reducer = combineReducers({loginReducer,channelReducer,queueReducer
});

5 react-router-dom

5.1 useNavigate

 用于在React应用程序中进行路由导航

const navigate = useNavigate();
navigate('/register', {replace: false});

5.2 useLocation

用于获取当前页面的 URL 信息。它返回一个包含当前 URL 信息的 location 对象,包括 pathname、search、hash 等属性。

import React from 'react';
import { useLocation } from 'react-router-dom';const MyComponent = () => {// 使用 useLocation hook 获取当前页面的 URL 信息const location = useLocation();return (<div><h1>当前页面的 URL 信息:</h1><p>Pathname: {location.pathname}</p><p>Search: {location.search}</p><p>Hash: {location.hash}</p></div>);
};export default MyComponent;

5.3 路由设置

路由配置:

import { Navigate, type RouteObject } from 'react-router-dom';
import { lazy, Suspense } from 'react';
const routes: RouteObject[] = [{path: '/',element: <Navigate to={LOGIN_PATH} />}
]
export { routes };

 项目启动入口:

import ReactDOM from 'react-dom/client';
import App from './App';
import './assets/css/base.css';
import './constant/format';
const root = ReactDOM.createRoot(document.getElementById('root')!);
root.render(<App />);

 App.tsx配置:

import { Suspense, useEffect, type ReactElement } from 'react';
import { Provider } from 'react-redux';
import 'antd/dist/reset.css';
import { HashRouter, useRoutes, useLocation, useNavigate } from 'react-router-dom';
import { routes } from './router';
import store from './store';
import './store/actionCreators';
import ErrorBoundary from './components/error';
import { CommonWrapper } from './assets/css/common';function App(): ReactElement {function RouteElement(props: any) {return useRoutes(routes);}return (<CommonWrapper><div className="App"><Provider store={store}><HashRouter><Suspense fallback={<div>wwww</div>}><ErrorBoundary><RouteElement /></ErrorBoundary></Suspense></HashRouter></Provider></div></CommonWrapper>);
}export default App;

 通过useRoutes(routes)将路由加载进去

5.4 withRouter

withRouter 是 React Router 提供的一个高阶组件(Higher-Order Component),用于将路由信息注入到组件中。它可以将 React Router 的 history、location 和 match 对象作为 props 传递给被包裹的组件。

import React from 'react';
import { withRouter } from 'react-router-dom';const MyComponent = ({ history, location, match }) => {// 在组件中可以访问到 history、location 和 match 对象return (<div><h1>当前页面的路径:</h1><p>Pathname: {location.pathname}</p>{/* 其他路由信息 */}</div>);
};// 使用 withRouter 高阶组件包裹组件
export default withRouter(MyComponent);

5.5 错误页面定义 

import React from 'react';
import { useNavigate } from 'react-router-dom';
function withRouter(WrapperComponent: any) {return function (props: any) {const navigate = useNavigate();const router = { navigate };return <WrapperComponent {...props} router={router} />;};
}
export default withRouter;

通过withRouter定义错误页面:

import React, { type ReactElement } from 'react';
import { Button, Result } from 'antd';
import withRouter from '../../hook/withRouter/withRouter';interface IProps {children: ReactElement;router: any;
}
interface IState {hasError: boolean;
}
class ErrorBoundary extends React.PureComponent<IProps, IState> {constructor(props: any) {super(props);this.state = { hasError: false };}
//静态方法,用于捕获子组件渲染过程中发生的错误,并更新组件的状态。在这里,如果发生了错误,则将 hasError 状态设置为 true。static getDerivedStateFromError(error: any) {return { hasError: true };}
//生命周期方法,用于捕获子组件渲染过程中发生的错误,并打印错误信息。在这里,将错误信息打印到控制台。componentDidCatch(error: any, errorInfo: any) {console.log(error, errorInfo);}loginRouter(): void {const { navigate } = this.props.router;navigate('/home/recommend');window.location.reload();}render() {if (this.state.hasError) {return (<Resultstatus="404"title="错误"subTitle="抱歉,页面好像出现了一个未知错误,请点击下方按钮跳转至首页"extra={<Buttontype="primary"onClick={() => {this.loginRouter();}}>首页</Button>}/>);}return this.props.children;}
}export default withRouter(ErrorBoundary);

6 自定义组件

const getSize = () => {return window.innerWidth > 1000 ? "large" : "small";
}
const useWindowSize = () => {const [size, setSize] = useState(getSize());useEffect(() => {const handler = () => {setSize(getSize())};window.addEventListener('resize', handler);return () => {window.removeEventListener('resize', handler);};}, []);return size;
};

使用:

const Demo = () => {const size = useWindowSize();if (size === "small") return <SmallComponent />;else return <LargeComponent />;
};

7 自定义Context

<Provider> 组件允许你通过 context prop 指定一个备用的上下文。如果你正在构建一个复杂的、可复用的组件,并且你不希望 store 与 consumer 应用程序可能使用的任何 Redux store 相冲突,那么这很有用。

要通过各种 hook API 访问备用上下文,请使用 hook creator 函数:

import React from 'react'
import {Provider,createStoreHook,createDispatchHook,createSelectorHook,
} from 'react-redux'const MyContext = React.createContext(null)// 如果想在其他文件使用自定义 hook,导出这些自定义 hook。
export const useStore = createStoreHook(MyContext)
export const useDispatch = createDispatchHook(MyContext)
export const useSelector = createSelectorHook(MyContext)const myStore = createStore(rootReducer)export function MyProvider({ children }) {return (<Provider context={MyContext} store={myStore}>{children}</Provider>)
}


http://www.mrgr.cn/p/63838100

相关文章

MsgPack文档

https://github.com/msgpack/msgpack/blob/master/spec.md

旅游攻略

0. 前言 记录一些已旅游城市的攻略,存档供之后参考。PS:有些攻略没记录,追悔莫及。 1. 绍兴一日游

【OceanBase诊断调优 】—— 如何快速定位SQL问题

作者简介&#xff1a; 花名&#xff1a;洪波&#xff0c;OceanBase 数据库解决方案架构师&#xff0c;目前负责 OceanBase 数据库在各大型互联网公司及企事业单位的落地与技术指导&#xff0c;曾就职于互联网大厂和金融科技公司&#xff0c;主导过多项数据库升级、迁移、国产化…

视频质量评价 PSNR 算法详细介绍

PSNR PSNR(Peak Signal-to-Noise Ratio,峰值信噪比)是一种常用的评价图像质量的指标,尤其在图像压缩和图像处理领域。它基于最大可能的图像信号功率和图像的噪声功率之间的比率,通常用于衡量图像恢复或图像压缩算法的效果。 原理 PSNR是基于MSE(Mean Squared Error,均…

检测硬盘读写速度

1. 在左下角搜索框输入“cmd”,并点击“以管理员身份运行”。 2. 输入命令“winsat disk -drive 盘符”,并点击“回车”。从上到下,分别是:✬ 随机读取速度: 179.36MB/s✬ 顺序读取速度: 414.64MB/s✬ 顺序写入速度: 208.79MB/s原文出处 https://baijiahao.baidu.com/s?i…

Web3技术解析:区块链在去中心化应用中的角色

引言 在过去几年中&#xff0c;Web3技术已经成为了互联网领域的一个热门话题。作为区块链技术的延伸&#xff0c;Web3不仅仅是数字货币的代名词&#xff0c;更是一个能够为各种应用提供去中心化解决方案的强大工具。本文将深入探讨区块链在Web3去中心化应用中的关键角色&#…

实验七 智能手机互联网程序设计(微信程序方向)实验报告

请编写一个用户登录界面&#xff0c;提示输入账号和密码进行登录&#xff0c;要求在输入后登陆框显示为绿色&#xff1b; 二、实验步骤与结果&#xff08;给出对应的代码或运行结果截图&#xff09; index.wxml <view class"content"> <view class"a…

02. x86处理器运行方式

【CPU指令】 CPU控制器通过读取存储器中的指令确定要执行的功能,CPU运行需要不停的读取指令,计算机启动后CPU会从固定地址处开始读取指令,首先读取 NOR Flash 存储器中的固件,固件执行完毕后引导操作系统执行。 指令是一个二进制数据,主要由如下两部分组成:1.操作码,设置…

hadoop安装记录

目录 零、版本说明一、环境准备1.1.规划1.2.准备 二、安装配置hadoop 三、启动 零、版本说明 centos [rootnode1 ~]# cat /etc/redhat-release CentOS Linux release 7.9.2009 (Core)jdk [rootnode1 ~]# java -version java version "1.8.0_311" Java(TM) SE Run…

Hadoop集群模式的搭建之二:配置Hadoop平台基础环境

在进行Hadoop集群的安装部署之前,需要对虚拟机进行一些基础环境配置。例如,为了在集群中识别主机,需要配置主机和IP地址的映射关系;为了使用Web相关的服务和访问连接,需要在集群中关闭并禁用防火墙功能;为了减少节点之间访问时人工输入用户密码,需要配置SSH免密登录;为…

【嵌入式】Arduino IDE + ESP32开发环境配置

一 背景说明 最近想捣鼓一下ESP32的集成芯片&#xff0c;比较了一下&#xff0c;选择Arduino IDE并添加ESP32支持库的方式来开发&#xff0c;下面记录一下安装过程以及安装过程中遇到的坑。 二 下载准备 【1】Arduino IDE ESP32支持一键安装包&#xff08;非常推荐&#xff0…

iOS - 多线程-读写安全

文章目录 iOS - 多线程-读写安全1. 多读单写1.1 场景1.2 实现方案1.2.1 pthread_rwlock&#xff1a;读写锁1.2.1.1 示例 1.2.2 dispatch_barrier_async&#xff1a;异步栅栏调用1.2.2.1 示例 iOS - 多线程-读写安全 假设有一个文件&#xff0c;A线程进行读取操作&#xff0c;B…

ICESat-2 从ATL08中获取ATL03分类结果

ICESat-2 ATL03数据和ATL08数据的分段距离不一致,ATL08在ATL03的基础上重新分段,并对分段内的数据做处理得到一系列的结果,详情见数据字典: ATL08 Product Data Dictionary (nsidc.org) ATL08使用DRAGANN算法对ATL03数据做了去噪处理,并使用分类算法对每个光子进行分类标志…

【C++打怪之路Lv3】-- 类和对象(上)

&#x1f308; 个人主页&#xff1a;白子寰 &#x1f525; 分类专栏&#xff1a;C打怪之路&#xff0c;python从入门到精通&#xff0c;数据结构&#xff0c;C语言&#xff0c;C语言题集&#x1f448; 希望得到您的订阅和支持~ &#x1f4a1; 坚持创作博文(平均质量分82)&#…

Fastbin attackDouble free和Unsortbin leak的综合使用

Fastbin attack&&Double free和Unsortbin leak的综合使用✅ 今天做一个综合题目,包括利用Fastbin attack实现多指针指向一个地址,以及利用Unsortbin leak泄露libc基地址和修改__malloc_hook地址为one_gadget 题目是buuctf上面的一道题目,题目链接 https://buuoj.cn/…

C语言Linux vim shell命令

无论是在插入模式或者是其他模式下对于文件的修改都是对于内存缓冲区进行修改&#xff0c;只有当点击w进行保存以后才会将数据写入到一个新的文件中的&#xff0c;将源文件删除&#xff0c;并且新文件改为文件的名字 1. actionmotion dG删到文件尾 ggdG先到开头再删除到末尾…

Java中的接口

package day38; ​ public interface Test1 {void say();int add(int a,int b); ​ } ​ package day38; ​ public interface Test2 {void printhelllo();double add(double a,double b); } ​ package day38; ​ public class Implementall implements Test1,Test2 {Overri…

AJAX——案例

1.商品分类 需求&#xff1a;尽可能同时展示所有商品分类到页面上 步骤&#xff1a; 获取所有的一级分类数据遍历id&#xff0c;创建获取二级分类请求合并所有二级分类Promise对象等待同时成功后&#xff0c;渲染页面 index.html代码 <!DOCTYPE html> <html lang&qu…

Java web应用性能分析之【sysbench基准测试】

Java web应用性能分析之【CPU飙高分析之MySQL】-CSDN博客 Java web应用性能分析之【Linux服务器性能监控分析概叙】-CSDN博客 Java web应用性能分析概叙-CSDN博客 Java web应用性能分析之【基准测试】-CSDN博客 上面基本科普了一下基准测试&#xff0c;这里我们将从sysbench…