Irbisa · Шпаргалка
Состояние и события
useState, состояние как снимок, батчинг, функция-апдейтер, иммутабельные обновления объектов и массивов, подъём состояния, события
Что такое состояние (state) в React и как работает
useState?type User = { name: string }; function Counter() { const [count, setCount] = useState(0); const [user, setUser] = useState<User | null>(null);…Почему изменение обычной локальной переменной не обновляет экран, а
useStateобновляет?Как обрабатывать события в React и как передать аргумент в обработчик?
type Item = { id: string; title: string }; function TodoList({ items, onRemove }: { items: Item[]; onRemove: (id: string) => void }) { function handleSubmit(e: React.FormEvent<HTMLFormElement>) { e.preventDefault(); // stop the full page reload console.log('submitted');…Найдите баг: этот компонент падает с ошибкой «Too many re-renders» при первом же рендере.
function Greeting({ name }: { name: string }) { const [upper, setUpper] = useState(''); setUpper(name.toUpperCase()); return <h1>{upper}</h1>;}Почему стейт нужно обновлять иммутабельно, а не менять объект или массив на месте?
Как обновить объект в стейте, в том числе вложенный?
type Person = { name: string; address: { city: string; zip: string } }; function Profile() { const [person, setPerson] = useState<Person>({ name: 'Ada', address: { city: 'London', zip: 'N1' },…Найдите баг: при вводе в поле поиска фильтр категории сбрасывается на вариант All.
type Filters = { query?: string; category?: string }; function ProductFilters() { const [filters, setFilters] = useState<Filters>({ category: 'books' }); return ( <> <input value={filters.query ?? ''} onChange={(e) => setFilters({ query: e.target.value })} /> <select value={filters.category ?? ''} onChange={(e) => setFilters({ category: e.target.value })}> <option value="">All</option> <option value="books">Books</option> </select> </> );}Как добавлять, удалять и обновлять элементы массива в стейте?
type Todo = { id: number; text: string; done: boolean }; function useTodos(initial: Todo[]) { const [todos, setTodos] = useState(initial); const add = (text: string) =>…Что значит «поднять состояние» (lifting state up) и когда это делают?
function Accordion() { const [openIndex, setOpenIndex] = useState(0); // lifted from the panels return ( <> <Panel title="About" isOpen={openIndex === 0} onOpen={() => setOpenIndex(0)} />…Что значит «состояние является снимком» (state as a snapshot) в React?
Что такое функция-апдейтер в сеттере стейта и когда её использовать?
function Counter() { const [count, setCount] = useState(0); function addThree() { setCount((c) => c + 1); setCount((c) => c + 1);…Что покажет alert и что покажет кнопка после одного клика и почему?
function Counter() { const [number, setNumber] = useState(0); function handleClick() { setNumber(number + 5); setNumber((n) => n + 1); setNumber(number + 1); alert(number); } return <button onClick={handleClick}>{number}</button>;}Что такое батчинг в React и что изменил автоматический батчинг в React 18?
import { flushSync } from 'react-dom'; function Chat() { const [items, setItems] = useState<string[]>([]); const [draft, setDraft] = useState(''); const listRef = useRef<HTMLUListElement>(null);…Найдите баг: после клика по «Add» новый тег не появляется, пока не начнёшь печатать в поле.
function Tags() { const [tags, setTags] = useState<string[]>(['react']); const [text, setText] = useState(''); function handleAdd() { tags.push(text); setTags(tags); } return ( <> <input value={text} onChange={(e) => setText(e.target.value)} /> <button onClick={handleAdd}>Add</button> <p>{tags.join(', ')}</p> </> );}Что происходит, если вызвать сеттер стейта с тем же значением, которое уже лежит в стейте?
Что такое ленивая инициализация стейта в
useStateи когда она нужна?function Notes() { // JSON.parse runs only on the first render const [notes, setNotes] = useState<string[]>(() => { const saved = localStorage.getItem('notes'); return saved ? (JSON.parse(saved) as string[]) : []; });…Как правильно спроектировать стейт компонента: что в нём хранить, а что нет?
Как работают
preventDefault,stopPropagationи обработчики фазы перехвата в React и куда React вешает слушатели событий?type CardProps = { onOpen: () => void; onShare: () => void }; function Card({ onOpen, onShare }: CardProps) { return ( <div onClick={onOpen} onClickCapture={() => console.log('capture: runs first')}> <a…Как обрабатывать частые события вроде
scroll,resizeилиpointermove, не перерисовывая компонент на каждое из них?function ArticleHeader() { const barRef = useRef<HTMLDivElement>(null); const [scrolled, setScrolled] = useState(false); useEffect(() => { let frame = 0;…Как реализовать undo и redo для части стейта в React?
type History<T> = { past: T[]; present: T; future: T[] };type HistoryAction<T> = { type: 'set'; value: T } | { type: 'undo' } | { type: 'redo' }; const LIMIT = 100; // keep memory bounded function historyReducer<T>(state: History<T>, action: HistoryAction<T>): History<T> {…