马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
useLayouEffect同步实行状态更新
useEffect()是在渲染被绘制到屏幕之后实行的,是异步的,useLayouEffect()是在渲染之后但是在屏幕更新之前,是同步的
大部门环境下我们采取useEffect(),性能更好,但是useEffect内里的操纵须要处置惩罚DOM,而且会改变页面的样式,就须要用useLayoutEffect,否则大概会出现闪屏题目- import { useEffect, useLayoutEffect, useReducer, useState } from "react";
- function App(){
- const [msg,setMsg] = useState('hello App')
- useLayoutEffect(()=>{
- for(let i =0;i<100000;i++){
- setMsg('App hello')
- }
- })
- return (
- <div>
- {msg}
- </div>
- )
- }
- export default App
复制代码 uselnsertionEffectDOM更新前触发
useInsertionEffect应用场景非常少,由于获取不到DOM元素,以是只在CSS-in-JS 库中才会利用
这是实行的序次:- import { useEffect,useLayoutEffect,useInsertionEffect } from "react"
- function App(){
- //触发时机:3 2 1
- useEffect(()=>{
- console.log(1)
- })
- useLayoutEffect(()=>{
- console.log(2)
- })
- useInsertionEffect(()=>{
- console.log(3)
- })
- return (
- <div>
- hello App
- </div>
- )
- }
- export default App
复制代码 突然出bug了问一下deepseek
这大唐笔
不祥的预感
起首 验证依赖安装状态- # 进入项目目录
- cd /root/NewLife/vite-project
- # 检查是否已安装 tailwindcss
- ls node_modules | grep tailwindcss
- # 如果没有输出结果,执行完整安装
- npm uninstall tailwindcss postcss autoprefixer
- npm install -D tailwindcss postcss autoprefixer@latest
复制代码 再逼迫重修设置文件- # 删除现有配置文件
- rm -f tailwind.config.js postcss.config.js
- # 重新初始化配置
- npx tailwindcss init -p --full
复制代码 我错了对不起- import { useEffect,useLayoutEffect,useInsertionEffect, useRef } from "react"
- function App(){
- //触发时机:3 2 1
- const ref = useRef(null)
- useInsertionEffect(()=>{
- const style = document.createElement('style')
- style.innerHTML = `
- .box{
- background:red;
- width:100px;
- height:100px
- }
- `
- document.head.appendChild(style)
- })
- return (
- <div>
- hello App
- <div className="box" ref = {ref}>aaaa</div>
- </div>
- )
- }
- export default App
复制代码 Reducer同一的状态管理聚集
对于拥有很多状态更新逻辑的组件来说,过于分散的变乱大概会令人不知所措,对于这种环境,可以将组件全部状态更新逻辑整合到一个外部函数中,这个函数叫做reducer
Reducer是处置惩罚状态的另一种方式- import { useState } from 'react'
- function App() {
- const [list, setList] = useState([
- { id: 1, text: 'aaa' },
- { id: 2, text: 'bbb' },
- { id: 3, text: 'ccc' },
- ])
- const handleAdd = () => {
- setList([...list, { id: 4, text: 'ddd' }])
- }
- const handleEdit = (id) => {
- setList(
- list.map((item) => {
- if (item.id === id) {
- return { ...item, text: 'new' + item.text }
- } else {
- return item
- }
- })
- )
- }
- const handleRemove = (id) => {
- setList(
- list.filter((item) => {
- if (item.id === id) {
- return false
- } else {
- return true
- }
- })
- )
- }
- return (
- <div>
- hello App
- <input type="text" />
- <button onClick={() => handleAdd()}>添加</button>
- <ul>
- {list.map((item) => {
- return(
- <li key={item.id}>
- {item.text}
- <button onClick={() => handleEdit(item.id)}>编辑</button>
- <button onClick={() => handleRemove(item.id)}>删除</button>
- </li>
- )
- })}
- </ul>
- </div>
- )
- }
- export default App
复制代码 这东西管理起来很贫困,以是最好会集管理- import { useReducer } from 'react'
- //由着reducer函数完成外部逻辑的统一处理
- function listReducer(state, action) {
- switch (action.type) {
- case 'add':
- return [...state, { id: 4, text: 'dddd' }]
- case 'edit':
- return state.map((item) => {
- if (item.id === action.id) {
- return { ...item, text: 'new' + item.text }
- } else {
- return item
- }
- })
- case 'remote':
- return state.filter((item) => {
- if (item.id === action.id) {
- return false
- } else {
- return true
- }})
- }
- }
- function App() {
- const [list, dispatch] = useReducer(listReducer, [
- { id: 1, text: 'aaa' },
- { id: 2, text: 'bbb' },
- { id: 3, text: 'ccc' },
- ])
- return (
- <div>
- hello App
- <input type="text" />
- <button onClick={() => dispatch({ type: 'add' })}>添加</button>
- <ul>
- {list.map((item) => {
- return (
- <li key={item.id}>
- {item.text}
- <button onClick={() => dispatch({ type: 'edit', id: item.id })}>
- 编辑
- </button>
- <button onClick={() => dispatch({ type: 'remote', id: item.id })}>
- 删除
- </button>
- </li>
- )
- })}
- </ul>
- </div>
- )
- }
- export default App
复制代码 reducer还提供了一个immer版本
现在来改造一下
useImmerReducer 是团结了 Immer 库和 React useReducer 的加强型 Hook,专为简化不可变状态更新而筹划。
- import { useImmerReducer } from 'use-immer'
- //由着reducer函数完成外部逻辑的统一处理
- function listReducer(draft, action) {
- switch (action.type) {
- case 'add':
- draft.push({ id: 4, text: 'ddd' })
- break
- case 'edit':
- const value = draft.find((item)=>item.id === action.id)
- value.text = 'new' + value.text
- break
- case 'remote':
- const index = draft.findIndex((item)=>item.id === action.id)
- draft.splice(index,1)
- break
- }
- }
- function App() {
- const [list, dispatch] = useImmerReducer(listReducer, [
- { id: 1, text: 'aaa' },
- { id: 2, text: 'bbb' },
- { id: 3, text: 'ccc' },
- ])
- return (
- <div>
- hello App
- <input type="text" />
- <button onClick={() => dispatch({ type: 'add' })}>添加</button>
- <ul>
- {list.map((item) => {
- return (
- <li key={item.id}>
- {item.text}
- <button onClick={() => dispatch({ type: 'edit', id: item.id })}>
- 编辑
- </button>
- <button onClick={() => dispatch({ type: 'remote', id: item.id })}>
- 删除
- </button>
- </li>
- )
- })}
- </ul>
- </div>
- )
- }
- export default App
复制代码 Context向组件深层通报数据
通常来说会通过props将信息从父组件通报到子组件,但是如果必须通过很多中心组件向下通报props,大概在应用中的很多组件须要雷同的信息,通报props会变得非常的冗长和未便- function App(){
- return (
- <div>
- hello App
- <Head count={123}/>
- </div>
- )
- }
- function Head({count}){
- return(
- <div>
- hello Head
- <Title count={count}/>
- </div>
- )
- }
- function Title({count}){
- return (
- <div>
- hello Title,{count}
- </div>
- )
- }
- export default App
复制代码 Context允许父组件向其下层无论多深的任何组件提供信息,而无需通过props显式通报- import { createContext,useContext } from "react"
- const Context = createContext()
- function App(){
- return (
- <div>
- hello App
- <Context.Provider value={123}>
- <Head/>
- </Context.Provider>
- </div>
- )
- }
- function Head({count}){
- return(
- <div>
- hello Head
- <Title count={count}/>
- </div>
- )
- }
- function Title({count}){
- const value = useContext(Context)
- return (
- <div>
- hello Title,{value}
- </div>
- )
- }
- export default App
复制代码 如许之后就是可以更方便的通报,如果要通报多个值就用数组大概对象
还可以添加默认值- import { createContext,useContext, useState } from "react"
- const Context = createContext(0)
- function App(){
- const [count,setCount] = useState(123)
- const handleClick=()=>{
- setCount(count+1)
- }
- return (
- <div>
- hello App
- <button onClick={handleClick}>点击</button>
- <Context.Provider value={count}>
- <Head/>
- </Context.Provider>
- </div>
- )
- }
- function Head({count}){
- return(
- <div>
- hello Head
- <Title count={count}/>
- </div>
- )
- }
- function Title({count}){
- const value = useContext(Context)
- return (
- <div>
- hello Title,{value}
- </div>
- )
- }
- export default App
复制代码 Reducer共同Context实现共享状态管理
Reducer可以整合组件的状态更新逻辑,Context可以将信息深入通报给其他组件,可以组合利用他们共同管理一个复杂页面的状态(兄弟状态共享)
存在更复杂的状态管理,可以采取三套方案,Redux,Mobx,Zustand等
ListContent,jsx:- function ListContent(){
- return(
- <ul>
- {
- list.map((item)=> {
- return(
- <li key={item.id}>{item.text}
- <button onClick={()=>listDispatch({type:'edit',id:item.id})}>编辑</button>
- <button onClick={()=>listDispatch({type:'remove',id:item.id})}>删除</button>
- </li>
- )
- })}
- </ul>
- )
- }
- export default ListContent
复制代码 ListHead.jsx:- import { useContext } from 'react'
- import {ListDispatchContext} from './ListProvider.jsx'
- function ListHead(){
- const listDispatch = useContext(ListDispatchContext)
- return(
- <>
- <input type="text" /><button onClick={()=>listDispatch({type:'add'})}>添加</button>
- </>
- )
- }
- export default ListHead
复制代码 ListProvider.jsx:- import {useReducer,createContext} from 'react'
- const ListContext = createContext()
- const ListDispatchContext = createContext()
- function listReducer(draft, action) {
- switch (action.type) {
- case 'add':
- draft.push({ id: 4, text: 'ddd' })
- break
- case 'edit':
- const value = draft.find((item)=>item.id === action.id)
- value.text = 'new' + value.text
- break
- case 'remote':
- const index = draft.findIndex((item)=>item.id === action.id)
- draft.splice(index,1)
- break
- }
- }
- function ListProvider({children}){
- const [list,listDispatch] = useReducer(listReducer,[
- {id:1,text:'aaa'},
- {id:2,text:'bbb'},
- {id:3,text:'ccc'},
- ])
- return(
- <ListContext.Provider value={list}>
- <ListDispatchContext.Provider value={listDispatch}>
- {children}
- </ListDispatchContext.Provider>
- </ListContext.Provider>
- )
- }
- export default ListProvider
复制代码 Reducer共同Context实现共享状态管理.jsx:- import ListContent from './ListContent'
- import ListHead from './ListHead'
- import ListProvider from './ListProvider'
- function App() {
- return (
- <div>
- hello App
- <ListProvider>
- <ListHead />
- <ListContent />
- </ListProvider>
- </div>
- )
- }
- export default App
复制代码 reducer管理.jsx:- import { useImmerReducer } from 'use-immer'
- //由着reducer函数完成外部逻辑的统一处理
- function listReducer(draft, action) {
- switch (action.type) {
- case 'add':
- draft.push({ id: 4, text: 'ddd' })
- break
- case 'edit':
- const value = draft.find((item)=>item.id === action.id)
- value.text = 'new' + value.text
- break
- case 'remote':
- const index = draft.findIndex((item)=>item.id === action.id)
- draft.splice(index,1)
- break
- }
- }
- function App() {
- const [list, dispatch] = useImmerReducer(listReducer, [
- { id: 1, text: 'aaa' },
- { id: 2, text: 'bbb' },
- { id: 3, text: 'ccc' },
- ])
- return (
- <div>
- hello App
- <input type="text" />
- <button onClick={() => dispatch({ type: 'add' })}>添加</button>
- <ul>
- {list.map((item) => {
- return (
- <li key={item.id}>
- {item.text}
- <button onClick={() => dispatch({ type: 'edit', id: item.id })}>
- 编辑
- </button>
- <button onClick={() => dispatch({ type: 'remote', id: item.id })}>
- 删除
- </button>
- </li>
- )
- })}
- </ul>
- </div>
- )
- }
- export default App
复制代码 memo在props稳定环境下跳过重新渲染
- import { useState } from "react"
- function Head(){
- return(
- <div>
- hello Head,{Math.random()}
- </div>
- )
- }
- function App(){
- const [count,setCount] = useState(0)
- const handleClick = ()=>{
- setCount(count+1)
- }
- return(
- <div>
- hello App
- <button onClick={handleClick}>点击</button>
- <Head />
- </div>
- )
- }
- export default App
复制代码 子组件会重新渲染吗?
会的
memo是在props没改变的时间跳过渲染,就可以办理count都没变但是Head还在变的题目- import { useState,memo } from "react"
- const Head = memo(function Head(){
- return(
- <div>
- hello Head,{Math.random()}
- </div>
- )
- })
- function App(){
- const [count,setCount] = useState(0)
- const handleClick = ()=>{
- setCount(count+1)
- }
- return(
- <div>
- hello App
- <button onClick={handleClick}>点击</button>
- <Head />
- </div>
- )
- }
- export default App
复制代码 useMemo对盘算效果举行缓存
- import { useState } from "react";
- import { memo } from "react";
- const Head = memo(function Head(){
- return(
- <div>hello Head,{Math.random()}</div>
- )
- })
- function App(){
- const [count,setCount] = useState(0)
- const [msg,setMsg]=useState('hello react')
- const list = [msg.toLowerCase(),msg.toUpperCase()]
- const handleClick =()=>{
- setCount(count + 1)
- }
- return (
- <div>
- hello App
- <button onClick={handleClick}>点击</button>
- <Head list={list}/>
- </div>
- )
- }
- export default App
复制代码 这个照旧会发生改变的,由于地点差异,就算是一样的数组也改变了,他以为是差异的
我们如果想要不让它变
就可以用useMEmo- import { useMemo, useState } from "react";
- import { memo } from "react";
- const Head = memo(function Head(){
- return(
- <div>hello Head,{Math.random()}</div>
- )
- })
- function App(){
- const [count,setCount] = useState(0)
- const [msg,setMsg]=useState('hello react')
- const list = useMemo(()=>[msg.toLowerCase(),msg.toUpperCase()],[msg])
- const handleClick =()=>{
- setCount(count + 1)
- }
- return (
- <div>
- hello App
- <button onClick={handleClick}>点击</button>
- <Head list={list}/>
- </div>
- )
- }
- export default App
复制代码 useCallback对函数举行缓存
useMemo的一种特例写法- import { useMemo, useState } from "react";
- import { memo } from "react";
- const Head = memo(function Head(){
- return(
- <div>hello Head,{Math.random()}</div>
- )
- })
- function App(){
- const [count,setCount] = useState(0)
- const [msg,setMsg]=useState('hello react')
- // const fn=()=>{
- // console.log(count+1)
- // }
- const fn = useMemo(()=>()=>{},[msg])
- const handleClick =()=>{
- setCount(count + 1)
- }
- return (
- <div>
- hello App
- <button onClick={handleClick}>点击</button>
- <Head fn={fn}/>
- </div>
- )
- }
- export default App
复制代码 如许利用回调函数也不会变,也可以引入useCallback- import { useMemo, useState,useCallback } from "react";
- import { memo } from "react";
- const Head = memo(function Head(){
- return(
- <div>hello Head,{Math.random()}</div>
- )
- })
- function App(){
- const [count,setCount] = useState(0)
- const [msg,setMsg]=useState('hello react')
- // const fn=()=>{
- // console.log(count+1)
- // }
- const fn = useCallback(()=>{console.log(msg)},[msg])
- const handleClick =()=>{
- setCount(count + 1)
- }
- return (
- <div>
- hello App
- <button onClick={handleClick}>点击</button>
- <Head fn={fn}/>
- </div>
- )
- }
- export default App
复制代码 就写到这吧嘻嘻嘻嘻西邮元哲来了
|