Изучение записей из трех измерений:
- почему 🤔️
- Как пользоваться 🔨
- Очки знаний⛽️
useState
Зачем использовать useState?
useState
Внешний вид: используйте класс в функциональных компонентахsetState
, Стимулировать!
Решаемая проблема заключается в следующем: когда функциональный компонент хочет иметь свое собственное поддерживаемое состояние, в крайнем случае его необходимо преобразовать в класс. Это очень хлопотно!
Как использовать useState?
const [name, setName] = useState('rose')
useState наступает на очки знаний ямы
😄1. Ключевые моменты:useState的初始值,只在第一次有效
В то время я не воспринимал это всерьез, пока не столкнулся с ямой...
🌰2. Например:
Когда я нажал кнопку изменить значение имени, я обнаружил, что в дочернем компоненте оно было получено, но не прошлоuseState
Присвоить имя!
Вывод: Практикуйте тестовые очки знаний! 😭
const Child = memo(({data}) =>{
console.log('child render...', data)
const [name, setName] = useState(data)
return (
<div>
<div>child</div>
<div>{name} --- {data}</div>
</div>
);
})
const Hook =()=>{
console.log('Hook render...')
const [count, setCount] = useState(0)
const [name, setName] = useState('rose')
return(
<div>
<div>
{count}
</div>
<button onClick={()=>setCount(count+1)}>update count </button>
<button onClick={()=>setName('jack')}>update name </button>
<Child data={name}/>
</div>
)
}
useEffect
Зачем использовать useEffect?
Внешний вид useEffect таков: использование функции жизненного цикла класса в функциональном компоненте или сочетание всех функций! Стимулировать!
Как использовать useEffect?
useEffect(()=>{
...
})
Сбор очков знаний useEffect
😄1. componentDidMount, который используется только в первый раз, можно использовать для запроса асинхронных данных...,
В конце useEffect добавление [] означает, что он выполняется только в первый раз.
useEffect(()=>{
const users = 获取全国人民的信息()
},[])
😄2.Используется для замены willUpdate и других жизненных функций, которые будут выполняться каждый раз при рендере
В конце useEffect, если вы не добавите [], это означает, что будет выполняться каждый рендеринг
useEffect(()=>{
const users = 每次都获取全国人民的信息()
})
😄3. Выполнение каждого рендера кажется немного дорогим, поэтому:
В конце useEffect добавляем [], а добавленное поле в [] означает, что это поле изменено, и мой эффект выполняется.
useEffect(() => {
const users = (name改变了我才获取全国人民的信息())
},[name])
😄4. Что делать, если я хочу разделить имя и возраст:
Можно написать несколько useEffects
useEffect(() => {
const users = (name改变了我才获取全国人民的name信息())
},[name])
useEffect(() => {
const users = (name改变了我才获取全国人民的age信息())
},[age])
😄5.Если мы подписались на что-то раньше, и окончательно отменили подписку в жизненном цикле willUnMount, как этого можно добиться с помощью useEffect:
Вы можете отписаться в возврате эффекта
useEffect(() => {
const subscription = 订阅全国人民吃饭的情报!
return () => {
取消订阅全国人民吃饭的情报!
}
},[])
Зачем отписываться?
Все мы знаем, что после рендеринга будет выполняться re-useEffect.Если в useEffect есть setInterval... Тогда каждый раз при рендеринге повторное выполнение useEffect будет создавать еще один setInterval, и тогда будет путаница... Можно вернуть следующий случай удалить содержимое
useEffect(() => {
console.log('use effect...',count)
const timer = setInterval(() => setCount(count +1), 1000)
return ()=> clearInterval(timer)
})
😄6.Некоторые секретные правила UseEffect:
1. Значение состояния, используемое в useEffect, фиксируется внутри useEffect и не будет изменено, пока useEffect не обновит и не зафиксирует значение состояния.
const [count, setCount] = useState(0)
useEffect(() => {
console.log('use effect...',count)
const timer = setInterval(() => {
console.log('timer...count:', count)
setCount(count + 1)
}, 1000)
return ()=> clearInterval(timer)
},[])
2.useEffect нельзя судить о пакете
const [count, setCount] = useState(0)
if(2 < 5){
useEffect(() => {
console.log('use effect...',count)
const timer = setInterval(() => setCount(count +1), 1000)
return ()=> clearInterval(timer)
})
}
3.useEffect нельзя прервать
const [count, setCount] = useState(0)
useEffect(...)
return // 函数提前结束了
useEffect(...)
}
Конкретная причина связана с правилами генерации и выполнения useEffect: см. документацию!
useRef
Зачем использовать useRef?
упоминалось ранее:
Значение состояния, используемое в useEffect, фиксируется внутри useEffect и не будет изменено, если только useEffect не обновит и не зафиксирует значение состояния.
const [count, setCount] = useState(0)
useEffect(() => {
console.log('use effect...',count)
const timer = setInterval(() => {
console.log('timer...count:', count)
setCount(count + 1)
}, 1000)
return ()=> clearInterval(timer)
},[])
useEffect
Значение состояния внутри фиксировано, есть способ решить эту проблему, просто используйтеuseRef
, можно понимать какuseRef
Роль:
Это эквивалентно глобальной области, одна изменяется, а другая обновляется...
Как использовать useRef?
const countRef = useRef(0)
Коллекция очков знаний useRef
😄 1. Эквивалент глобальной области видимости, одна модифицируется, а другая обновляется...
const [count, setCount] = useState(0)
const countRef = useRef(0)
useEffect(() => {
console.log('use effect...',count)
const timer = setInterval(() => {
console.log('timer...count:', countRef.current)
setCount(++countRef.current)
}, 1000)
return ()=> clearInterval(timer)
},[])
😄 2. Общая операция, используемая для работы с домом
const btnRef = useRef(null)
click me
Живи и учись, не забудь отвязать событие! return ()=> btnRef.current.removeEventListener('щелчок',onClick, false)
const Hook =()=>{
const [count, setCount] = useState(0)
const btnRef = useRef(null)
useEffect(() => {
console.log('use effect...')
const onClick = ()=>{
setCount(count+1)
}
btnRef.current.addEventListener('click',onClick, false)
return ()=> btnRef.current.removeEventListener('click',onClick, false)
},[count])
return(
<div>
<div>
{count}
</div>
<button ref={btnRef}>click me </button>
</div>
)
}
useMemo
Зачем использовать useMemo?
Например 🌰:
const Child = memo(({data}) =>{
console.log('child render...', data.name)
return (
<div>
<div>child</div>
<div>{data.name}</div>
</div>
);
})
const Hook =()=>{
console.log('Hook render...')
const [count, setCount] = useState(0)
const [name, setName] = useState('rose')
const data = {
name
}
return(
<div>
<div>
{count}
</div>
<button onClick={()=>setCount(count+1)}>update count </button>
<Child data={data}/>
</div>
)
}
Когда мы нажимаем кнопку, чтобы обновить счетчик, компонент Effect будет отображаться.После рендеринга выполняется эта строка кода:
const data = {
name
}
Эта строка кода сгенерирует объект с новым адресом памяти, так что даже с дочерним компонентом памятки он будет перерендерен, хотя значение, используемое дочерним элементом, в итоге не изменилось!
Таким образом, рендеринг является излишним, и это похоже на пустую трату производительности! тогдаuseMemo
Он пришел как человек с возможностью временного хранения.
Как использовать useMemo?
const data = useMemo(()=>{
return {
name
}
},[name])
, сначала он будет основан на[name]
Судите о значении имени внутри, потому чтоuseMemo
В качестве возможности временного хранения результат по фамилии временно сохраняется.
В итоге, сравнив фамилию, мы обнаружили, что значение имени не изменилось! Тогда на этот раз данные не будут переназначены новому объекту!
Без новых объектов не будет новых адресов памяти, поэтому Child не будет перерисовываться!
const Child = memo(({data}) =>{
console.log('child render...', data.name)
return (
<div>
<div>child</div>
<div>{data.name}</div>
</div>
);
})
const Hook =()=>{
console.log('Hook render...')
const [count, setCount] = useState(0)
const [name, setName] = useState('rose')
const data = useMemo(()=>{
return {
name
}
},[name])
return(
<div>
<div>
{count}
</div>
<button onClick={()=>setCount(count+1)}>update count </button>
<Child data={data}/>
</div>
)
}
Коллекция очков знаний useMemo
useMemo
На первый взгляд мне кажется, что с памяткой какие-то медовые отношения, потому что есть памятка...
😄 1. Во-первых,memo
Использование:函数组件里面的PureComponent
Однако, если функциональный компонент обернут в React.memo и имеет в своей реализации хук useState или useContext, он все равно будет повторно отображаться при изменении контекста.
😄 2. И,memo
Это поверхностное сравнение, что означает, что объект сравнивает только адрес памяти.Пока ваш адрес памяти не изменится, независимо от постоянно меняющегося значения в вашем объекте, рендеринг не будет запущен.
😄 3. Наконец,useMemo
Эффект,
тогдаuseMemo
В качестве временной способности хранения здесь идет:
useCallback
Зачем использовать useCallback?
useMemo решает проблему кэширования значений, а как насчет функций?
Следующее 🌰 заключается в том, что при нажатии кнопки счетчика рендеринг компонента «Эффект» обнаруживает:
const onChange=(e)=>{
setText(e.target.value)
}
Затем регенерируйтеonChange
Функция назначается дочернему компоненту, неглубокое сравнение не выполняется, и дочерний компонент успешно выполняет повторную визуализацию, хотя дочерний компонент ничего не делает!
const Child = memo(({data, onChange}) =>{
console.log('child render...')
return (
<div>
<div>child</div>
<div>{data}</div>
<input type="text" onChange={onChange}/>
</div>
);
})
const Hook =()=>{
console.log('Hook render...')
const [count, setCount] = useState(0)
const [name, setName] = useState('rose')
const [text, setText] = useState('')
const onChange=(e)=>{
setText(e.target.value)
}
return(
<div>
<div>count: {count}</div>
<div>text : {text}</div>
<button onClick={()=>setCount(count + 1)}>count + 1</button>
<Child data={name} onChange={onChange}/>
</div>
)
}
Как использовать useCallback?
const onChange = useCallback((e)=>{
setText(e.target.value)
},[])
Коллекция очков знаний useCallback
😄1.useMemo
иuseCallback
Аналогично, у всех есть функция кэширования. Существенной разницей может быть:
useMemo — это кешированное значение
useCallback — это функция кеша
😄2.Зависимости нет, добавление пустой зависимости - это пустой массив!
useReducer
Зачем использовать useReducer?
Как следует из названия,useReducer
Это редуктор в классе
Как использовать useReducer?
Например 🌰:
const reducer =(state = 0, {type})=>{
switch (type) {
case "add":
return state+1
case 'delete':
return state-1
default:
return state;
}
}
const Hook =()=>{
const [count, dispatch] = useReducer(reducer, 0)
return(
<div>
count:{count}
<button onClick={()=> dispatch({type:'add'})}>add</button>
<button onClick={()=> dispatch({type:'delete'})}>delete</button>
</div>
)
}
export default Hook
Коллекция очков знаний useReducer
Пока ничего особенного... 😼
useContext
Зачем использовать useContext?
useContext
Это контекст в классе.
Как использовать useContext?
import React, {useContext, useReducer} from 'react'
const reducer = (state = 0, {type}) => {
switch (type) {
case "add":
return state + 1
case 'delete':
return state - 1
default:
return state;
}
}
const Context = React.createContext(null);
const Child = () => {
const [count, dispatch] = useContext(Context)
return (
<div>
<div>child...{count}</div>
<button onClick={() => dispatch({type: 'add'})}>child add</button>
<button onClick={() => dispatch({type: 'delete'})}>child delete</button>
</div>
)
}
const Hook = () => {
const [count, dispatch] = useReducer(reducer, 10)
return (
<Context.Provider value={[count, dispatch]}>
<div>
<div>mom ... {count}</div>
<Child/>
<button onClick={() => dispatch({type: 'add'})}>mom add</button>
<button onClick={() => dispatch({type: 'delete'})}>mom delete</button>
</div>
</Context.Provider>
)
}
export default Hook
Коллекция точек знаний useContext
Пока ничего особенного... 😼
Крючки на заказ!
Настройте хук, который прислушивается к ширине и высоте окна при изменении размера
import {useEffect, useState} from "react";
export const useWindowSize = () => {
const [width, setWidth] = useState()
const [height, setHeight] = useState()
useEffect(() => {
const {clientWidth, clientHeight} = document.documentElement
setWidth(clientWidth)
setHeight(clientHeight)
}, [])
useEffect(() => {
const handleWindowSize = () =>{
const {clientWidth, clientHeight} = document.documentElement
setWidth(clientWidth)
setHeight(clientHeight)
};
window.addEventListener('resize', handleWindowSize, false)
return () => {
window.removeEventListener('resize',handleWindowSize, false)
}
})
return [width, height]
}
как пользоваться:
const [width, height] = useWindowSize()