flushSync强制刷新
如果不强制刷新是这样:每次count在下一轮才更新
import { useState, useRef } from 'react'
import { flushSync } from 'react-dom'
function App() {
const [count, setCount] = useState(0)
const ref=useRef(null)
const handleClick = () => {
setCount(count + 1)
console.log(ref.current.innerHTML)
}
return (
<div>
<button onClick={handleClick}></button>
<div ref={ref}>{count}</div>
</div>
)
}
export default App;
引入强制刷新:
import { useState, useRef } from 'react'
import { flushSync } from 'react-dom'
function App() {
const [count, setCount] = useState(0)
const ref=useRef(null)
const handleClick = () => {
flushSync(() => {
setCount(count + 1)
console.log(ref.current.innerHTML)
})
}
return (
<div>
<button onClick={handleClick}></button>
<div ref={ref}>{count}</div>
</div>
)
}
export default App;
react自动进行批处理,一次按按钮修改两次count,最终一起渲染,叫自动批处理
import { useState } from 'react'
import { flushSync } from 'react-dom'
function App() {
const [count, setCount] = useState(0)
const [count1, setCount1] = useState(0)
const handleClick = () => {
flushSync(() => {
setCount(count + 1)
setCount1(count1 + 1)
})
console.log(
'修改了一次'
)
}
return (
<div>
<button onClick={handleClick}>按钮</button>
<div >{count},{count1}</div>
</div>
)
}
export default App;
使用error boundary捕获渲染错误
例如在App组件里调用了Head组件,如果Head组件出错的话,正常情况是会影响整个界面的渲染的
我们想要的效果是当Head组件出错时,单独抛出Head组件的问题,并且不影响其他组件执行,需要用到一些第三方库:react-error-boundary
下载
# npm
npm install react-error-boundary
# pnpm
pnpm add react-error-boundary
# yarn
yarn add react-error-boundary
使用方法
<ErrorBoundary fallback={<div>Something went wrong</div>}>
<ExampleApplication />
</ErrorBoundary>
如果Head还出错,也不会影响其他组件的渲染,并且打印Head的错误
懒加载
用到的时候再加载,不用的时候不加载,节省性能
//App.jsx
import MyHead from './MyHead.jsx'
function Head() {
return (
<div>
<h1>头部</h1>
</div>
)
}
function App() {
return (
<div>
{/* <MyHead /> */}
</div>
)
}
export default App;
//MyHead.jsx
console.log('MyHead.jsx is running...');
function MyHead() {
return (
<div>
<h1>My Head</h1>
</div>
);
}
export default MyHead;
如果引入组件不使用组件,组件还是会加载一遍的
如果在用户没用到这些组件的时候就加载,会大大滴降低性能
import{useState,lazy,Suspense }from 'react'
const MyHead = lazy(() => import('./MyHead.jsx'))
//lazy需要接收一个promise对象,import()返回的是一个promise对象,符合lazy的要求,且语句执行到这里时,不加载
//使用时才加载
function App() {
const [show,setShow]=useState(false)
return (
<div>
<button onClick={() => setShow(true)}>点击我触发MyHead</button>
<Suspense fallback={<div>loading</div> } >
{show&&<MyHead/>}
</Suspense >
</div>
)
}
export default App;
这样就只会在触发MyHead按钮的时候显示MyHead组件了
点击按钮如果网速过慢,还可以显示loading的过程:
createPortal渲染Dom的不同部分
作用是将子组件渲染到 DOM 树中的指定节点,而不是父组件的 DOM 结构中
import {createPortal} from 'react-dom'
function App() {
return (
<div>
{createPortal( <p>这是一个段落</p>,document.querySelector('body'))}
</div>
)
}
export default App;
结构如下
可以用createPortal
将模态框渲染到 body
节点,避免受到父组件样式的影响。
<Profiler>和ReactDevTools的性能测试
import { useState ,Profiler} from "react"
function Head({count}) {
return (
<div>
hello Head{count}
</div>
)
}
function App() {
const [count, setCount] = useState(0)
const onRender = (id, phase, actualDuration, baseDuration, startTime, commitTime, interactions) => {
console.log(id, phase, actualDuration, baseDuration, startTime, commitTime, interactions)
}
return (
<div>
<button onClick={() => { setCount(count + 1) }}>点击</button>
{count}
<Profiler id='Head' onRender={onRender}>
{/* {需要id属性,确认你要测试的是哪个组件} */}
<Head count={count} /></Profiler>
</div>
)
}
export default App;
每次 Head
组件渲染时,onRender
回调函数都会被调用,并打印性能数据到控制台。
总之就是用作分析性能的
hydrateRoot水合与服务的API
CSS-in-JS可以在js里写css
下个库
npm install styled-components
使用库
import styled from 'styled-components'
const Div = styled.div`
width:200px;
height:200px;
background-color:red;
`
const Link = styled.a`
text-decoration:underline;
color:red`
function App() {
return (
<div>
<Div />
<Link>去百度</Link>
</div>
)
}
export default App
给Link里的链接加上伪类选择器
const Link = styled.a`
text-decoration:underline;
color:red
&:hover{}`
鼠标hover上去会变黄色
import styled from 'styled-components'
const Div = styled.div`
width:200px;
height:200px;
background-color:red;
`
const Link = styled.a`
text-decoration:underline;
color:red;
&:hover{
color:yellow;
}`
function App() {
return (
<div>
<Div />
<Link href='https://www.baidu.com'>去百度</Link>
</div>
)
}
export default App
如果前面不加&,就是给Div的子类添加hover
import styled from 'styled-components'
const Div = styled.div`
width:200px;
height:200px;
background-color:red;
p{
color:blue;
}
`
const Link = styled.a`
text-decoration:underline;
color:red;
&:hover{
color:yellow;
}`
function App() {
return (
<div>
<Div><p>嘻嘻嘻我是p</p> </Div >
<Link href='https://www.baidu.com'>去百度</Link>
</div>
)
}
export default App
控制display属性,使用模板字符串
import { useState } from 'react'
import styled from 'styled-components'
const Div = styled.div`
width:200px;
height:200px;
display:${({show})=>show?'block':'none'};
background-color:red;
p{
color:blue;
}
`
const Link = styled.a`
text-decoration:underline;
color:red;
&:hover{
color:yellow;
}`
function App() {
const [show,setShow]=useState(true)
return (
<div>
<button onClick={() => setShow(!show)}>切换显示</button>
<Div title='hello world' show={show}><p>嘻嘻嘻我是p</p> </Div >
<Link href='https://www.baidu.com' >去百度</Link>
</div>
)
}
export default App
React里使用TailwindCSS
弹幕说这个很好用
使用 Vite 安装 Tailwind CSS - Tailwind CSS
行吧我没学会用就这样吧
喝了小酒我又回来了
//index.css
@tailwind base;
@tailwind components;
@tailwind utilities;
//App.jsx
export default function App() {
return (
<h1 className="text-3xl font-bold underline">
Hello, Vite!
</h1>
);
}
//vite配置
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react-swc'
// https://vite.dev/config/
export default defineConfig({
plugins: [react(), tailwindcss()],
})
react-spring动画库
pmndrs/react-spring: ✌️ A spring physics based React animation library
# Install the entire library
npm install react-spring
# or just install your specific target (recommended)
npm install @react-spring/web
import { useState } from 'react'
import { useSpring, animated } from "@react-spring/web";
const FadeIn = ({ isVisible, children }) => {
const styles = useSpring({
opacity: isVisible ? 1 : 0,
y: isVisible ? 0 : 24,
})
return <animated.div style={styles}>{children}</animated.div>
}
function App() {
const [isVisible, setIsVisible] = useState(true)
return (
<div>
<button onClick={()=>setIsVisible(!isVisible) }></button>
<FadeIn isVisible={isVisible}>hello App</FadeIn>
</div>
)
}
export default App;
可以实现淡入淡出的效果
import { useState } from 'react'
import { useSpring, animated } from "@react-spring/web";
const FadeIn = ({ isVisible, children }) => {
const styles = useSpring({
opacity: isVisible ? 1 : 0,
y: isVisible ? 0 : 24,
})
return (<animated.div style={styles}>{children}
<animated.span>{ styles.y.to((val) => val.toFixed(0))}</animated.span>
</animated.div>
)
}
function App() {
const [isVisible, setIsVisible] = useState(true)
return (
<div>
<button onClick={()=>setIsVisible(!isVisible) }></button>
<FadeIn isVisible={isVisible}>hello App</FadeIn>
</div>
)
}
export default App;
点击以后数字会改变
Ant Design Charts图表库和echarts for react
zustnd 小浣熊
算了加载不出来
蚊子咬学长推了这个echarts for react
import React, { useEffect } from 'react';
import ReactECharts from 'echarts-for-react';
const MyChart = () => {
// 这里定义图表的 option 配置
const getOption = () => ({
title: {
text: 'ECharts 示例',
},
tooltip: {},
xAxis: {
data: ['A', 'B', 'C', 'D', 'E'],
},
yAxis: {},
series: [
{
name: '销量',
type: 'bar',
data: [5, 20, 36, 10, 10],
},
],
});
// 处理图表准备完毕的回调
const onChartReadyCallback = () => {
console.log('Chart is ready');
};
// 处理图表事件
const EventsDict = {
click: (params) => {
console.log('Chart clicked', params);
},
};
return (
<div>
<ReactECharts
option={getOption()}
notMerge={true}
lazyUpdate={true}
theme="light"
onChartReady={onChartReadyCallback}
onEvents={EventsDict}
opts={{ renderer: 'canvas' }} // 你可以设置更多选项
/>
</div>
);
};
export default MyChart;