Форки и зависимости
В работе синьора или миддла возникает такой момент, когда “хватит это терпеть!”©
И делаешь форк какой-нибудь супер либы, потому что уже год не хотят поправить злой баг, который похоже аффектит только твою работу.
А что делать потом? Надо же проверить, как изменения работают в твоем приложении.
И тут у нас варианты:
1. Правки залить на гитхабы и создать pull request в родительский репозиторий. Затем ждать когда их примут и опубликуют в npm. Выглядит жуть как долго и неудобно.
2. Переназначить зависимость на свой git репозиторий. Например так
3. Деплоить изменения прямиком в node_modules приложения. Дешево, сердито и костыль
4. Использовать yarn link
Делаем
Последний вариант выглядит интересней всего, но есть нюанс из-за которого, не разобравшись, мне пришлось выбрать третий вариант в далеком(нет) прошлом.
Если эта библиотечка имеет в dependencies какую то зависимость, которая должна быть только одна, например vue или react, то мы получим кучу левых ошибок, из которых не сразу разберем, что дело в link.
Например такое
Нужно дополнительно сделать link этих зависимостей
Happy contributing :)
P.S. Эта история работает так же и при разработке своих либ и создании example к ним. Только нужно указать зависимости через link - "react": "link:../node_modules/react" . Так же можно использовать https://www.npmjs.com/package/create-react-library которая сразу создаст папку example с правильно подключенными зависимостями.
Ну и по традиции, лайки там, дизлайки, реакции
#react #vue
В работе синьора или миддла возникает такой момент, когда “хватит это терпеть!”©
И делаешь форк какой-нибудь супер либы, потому что уже год не хотят поправить злой баг, который похоже аффектит только твою работу.
А что делать потом? Надо же проверить, как изменения работают в твоем приложении.
И тут у нас варианты:
1. Правки залить на гитхабы и создать pull request в родительский репозиторий. Затем ждать когда их примут и опубликуют в npm. Выглядит жуть как долго и неудобно.
2. Переназначить зависимость на свой git репозиторий. Например так
"super-lib": "git+https://github.com/org/super-lib.git",Ну и инсталлить изменения оттуда, что, конечно, быстрей чем первый вариант, но все равно не очень.
3. Деплоить изменения прямиком в node_modules приложения. Дешево, сердито и костыль
4. Использовать yarn link
Делаем
yarn linkв root дирректории форка, затем заходим в наше приложение и делаем
yarn link super-libТаким образом зависимость линкуется прямиком в локальную дирректорию без изменения package.json
Последний вариант выглядит интересней всего, но есть нюанс из-за которого, не разобравшись, мне пришлось выбрать третий вариант в далеком(нет) прошлом.
Если эта библиотечка имеет в dependencies какую то зависимость, которая должна быть только одна, например vue или react, то мы получим кучу левых ошибок, из которых не сразу разберем, что дело в link.
Например такое
Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:Решение
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.
или
[Vue warn]: $listeners is readonly.
[Vue warn]: $attrs is readonly.
Нужно дополнительно сделать link этих зависимостей
cd /mysuperfork/node_modules/reactДля vue нужно линкануть сам vue и vue-template-compiler
yarn link
cd ../react-dom
yarn link
cd app
yarn link react
yarn link react-dom
Happy contributing :)
P.S. Эта история работает так же и при разработке своих либ и создании example к ним. Только нужно указать зависимости через link - "react": "link:../node_modules/react" . Так же можно использовать https://www.npmjs.com/package/create-react-library которая сразу создаст папку example с правильно подключенными зависимостями.
Ну и по традиции, лайки там, дизлайки, реакции
#react #vue
👍9
Разрабатываем форму авторизации на React, XState, MobX
В этой статье мы поговорим про инструмент из серии "как я раньше без него жил" XState
Он не только для React, а для чего угодно - eсть модули для Vue, Svelte и можно свое написать для любого фреймворка
Мне в React всегда не нравились smart компоненты. Это когда в компонент намешано куча useState, useEffect, бизнес логика и вот это вот все.
Вынос всего этого добра в хуки с одной стороны решает проблему, но вся эта мешанина просто едет в хук. Особенную боль в этом случае доставляет form logic...
Вот возьмем например форму входа на сайт. Казалось бы, что там делать? 2 инпута, кнопка, дернули API, авторизовали - PROFIT!
Однако, есливключить голову сделать аналитику фичи более детально, окажется, что не все так просто:
1. Форма входа должна обрабатывать ошибки ввода
2. Форма входа не должна показывать ошибки пока поле не заполнено
3. Ошибка поля должна пропадать после ввода данных
4. Поле должно валидироваться явно (с показом ошибки) только после blur события
5. Не должно быть возможность отправить форму, пока есть ошибки валидации
6. Поля должны валидироваться не явно, для требования 5
7. После нажатия на кнопку отправки формы, кнопка должна исчезать и исключать повторную отправку формы
8. Ошибки сервера должны выводится в читаемом виде и не блокировать повторную отправку формы
9. После успешной авторизации форма не должна выводится. Вместо этого должно показываться сообщение, что пользователь уже авторизован
Вот так. 9 требований для простой формы авторизации из 2 полей без всяких там 2FA.
Я думаю вы уже представили как это реализовывать...
Но здесь нам приходит на помощь... дискретная математика...
Далее с картинками, мемчиками и кодом тут https://bearlogin.dev/blog/xstate-react-mobx-form-logic
Это мой новый сайт, который я собрал за вечер и залил на vdsina. https://vdsina.ru/?partner=pu792sk4w7 - вот ссылка на 10% скидоса вам, и 10% вознаграждения мне
Upd. Фиксанул отображение статьи на мобиле
#frontend #react #xstate #mobx #tutorials
В этой статье мы поговорим про инструмент из серии "как я раньше без него жил" XState
Он не только для React, а для чего угодно - eсть модули для Vue, Svelte и можно свое написать для любого фреймворка
Мне в React всегда не нравились smart компоненты. Это когда в компонент намешано куча useState, useEffect, бизнес логика и вот это вот все.
Вынос всего этого добра в хуки с одной стороны решает проблему, но вся эта мешанина просто едет в хук. Особенную боль в этом случае доставляет form logic...
Вот возьмем например форму входа на сайт. Казалось бы, что там делать? 2 инпута, кнопка, дернули API, авторизовали - PROFIT!
Однако, если
1. Форма входа должна обрабатывать ошибки ввода
2. Форма входа не должна показывать ошибки пока поле не заполнено
3. Ошибка поля должна пропадать после ввода данных
4. Поле должно валидироваться явно (с показом ошибки) только после blur события
5. Не должно быть возможность отправить форму, пока есть ошибки валидации
6. Поля должны валидироваться не явно, для требования 5
7. После нажатия на кнопку отправки формы, кнопка должна исчезать и исключать повторную отправку формы
8. Ошибки сервера должны выводится в читаемом виде и не блокировать повторную отправку формы
9. После успешной авторизации форма не должна выводится. Вместо этого должно показываться сообщение, что пользователь уже авторизован
Вот так. 9 требований для простой формы авторизации из 2 полей без всяких там 2FA.
Я думаю вы уже представили как это реализовывать...
Но здесь нам приходит на помощь... дискретная математика...
Далее с картинками, мемчиками и кодом тут https://bearlogin.dev/blog/xstate-react-mobx-form-logic
Это мой новый сайт, который я собрал за вечер и залил на vdsina. https://vdsina.ru/?partner=pu792sk4w7 - вот ссылка на 10% скидоса вам, и 10% вознаграждения мне
Upd. Фиксанул отображение статьи на мобиле
#frontend #react #xstate #mobx #tutorials
🔥9
Обработка форм
Очень часто при создании форм на React/Vue разработчики вешают обработку отправки на клик по кнопке сабмита. (Сам так делал :))
В итоге получаем проблему - нужно реализовывать стандартное поведение отправки формы, например по кнопке Enter.
Решение: добавить элемент form (как деды делали) и повесить обработку на onSubmit.
PROFIT!
#advice #vue #react #frontend
Очень часто при создании форм на React/Vue разработчики вешают обработку отправки на клик по кнопке сабмита. (Сам так делал :))
В итоге получаем проблему - нужно реализовывать стандартное поведение отправки формы, например по кнопке Enter.
Решение: добавить элемент form (как деды делали) и повесить обработку на onSubmit.
PROFIT!
#advice #vue #react #frontend
👍15👎1
Beta React Docs
Вчера наткнулся на Beta новой документации React
https://beta.reactjs.org/
Ну я вам скажу, это небо и земля вообще...
Просто сравните док по useCallback в старом и новом...
https://reactjs.org/docs/hooks-reference.html#usecallback
https://beta.reactjs.org/apis/react/useCallback
Собственно, искал инфу чтобы сделать пост про useCallback, но с такой докой уже можно не делать :)
#docs #react #frontend #дока2
Вчера наткнулся на Beta новой документации React
https://beta.reactjs.org/
Ну я вам скажу, это небо и земля вообще...
Просто сравните док по useCallback в старом и новом...
https://reactjs.org/docs/hooks-reference.html#usecallback
https://beta.reactjs.org/apis/react/useCallback
Собственно, искал инфу чтобы сделать пост про useCallback, но с такой докой уже можно не делать :)
#docs #react #frontend #дока2
react.dev
React is the library for web and native user interfaces. Build user interfaces out of individual pieces called components written in JavaScript. React is designed to let you seamlessly combine components written by independent people, teams, and organizations.
🔥10😁2
Прикольный пакет для всяких штук с ресайзами для React
https://github.com/johnwalley/allotment
Можно пилить свой vscode :)
#react #packages
https://github.com/johnwalley/allotment
Можно пилить свой vscode :)
#react #packages
GitHub
GitHub - johnwalley/allotment: A React component for resizable split views
A React component for resizable split views. Contribute to johnwalley/allotment development by creating an account on GitHub.
👍5
Хороший туториал по миграции с CRA на Vite https://cathalmacdonnacha.com/migrating-from-create-react-app-cra-to-vite
Собсно кто не в курсе, CRA изначально не планировался для продакшна, но очень много продакшнов его юзают. И сейчас в обсуждении замена рекомендации по дефолту и для новичков на Vite https://github.com/reactjs/reactjs.org/pull/5487
Я кстати давно еще советовал юзать Витю вместо CRA, но на меня там сразу ополчились разные идейные элементы, чой то я тут посмел джунам советовать вражеский инструмент :)
#react #vite
Собсно кто не в курсе, CRA изначально не планировался для продакшна, но очень много продакшнов его юзают. И сейчас в обсуждении замена рекомендации по дефолту и для новичков на Vite https://github.com/reactjs/reactjs.org/pull/5487
Я кстати давно еще советовал юзать Витю вместо CRA, но на меня там сразу ополчились разные идейные элементы, чой то я тут посмел джунам советовать вражеский инструмент :)
#react #vite
Everyday Frontend 🚀
Migrating from Create React App (CRA) to Vite
I recently migrated a production app within my company from create-react-app (CRA) to Vite, and the results have been great so far!
In this article, I go through all the steps I took as part of the migration, in the hope that it might help others who...
In this article, I go through all the steps I took as part of the migration, in the hope that it might help others who...
👍8
Псс... есть варик залететь в крутой стартап с крутыми фаундерами на правах ко-фаундера!
Проект выходного дня, фултайм не нужен.
Из особенностей - Elm на фронте https://elm-lang.org/.
Даже если не знаешь его (я бы удивился, если бы знал), но есть желание его изучить, то пиши мне в лс @bearlogin :)
P.S. хороший гайд по Elm https://elmprogramming.com/who-this-book-is-for.html
P.P.S. если знаешь React, тоже пиши, так как есть вариант написать часть проекта на React или вообще все переписать...
P.P.P.S - почему Elm? Потому что так исторически сложилось...
#стартап #elm #react
Проект выходного дня, фултайм не нужен.
Из особенностей - Elm на фронте https://elm-lang.org/.
Даже если не знаешь его (я бы удивился, если бы знал), но есть желание его изучить, то пиши мне в лс @bearlogin :)
P.S. хороший гайд по Elm https://elmprogramming.com/who-this-book-is-for.html
P.P.S. если знаешь React, тоже пиши, так как есть вариант написать часть проекта на React или вообще все переписать...
P.P.P.S - почему Elm? Потому что так исторически сложилось...
#стартап #elm #react
👍5
React useReducer
Я вижу много кода и часто замечаю, что useReducer незаслуженно обходят вниманием, предпочитая решать все через useState.
Чаще всего это происходит потому, что люди либо не знают про такой хук, либо слышали, но никогда не использовали.
При этом useReducer позволяет писать более читабельный и элегантный код для работы с стейтом компонента. Особенно хорош для сложной логики, но бывает и полезен для простых задач: булевые переключатели, формы и т.д.
Сравните два примера:
Или пример с объектами:
#frontend #react #hooks #state
Я вижу много кода и часто замечаю, что useReducer незаслуженно обходят вниманием, предпочитая решать все через useState.
Чаще всего это происходит потому, что люди либо не знают про такой хук, либо слышали, но никогда не использовали.
При этом useReducer позволяет писать более читабельный и элегантный код для работы с стейтом компонента. Особенно хорош для сложной логики, но бывает и полезен для простых задач: булевые переключатели, формы и т.д.
Сравните два примера:
const [isEnabled, setIsEnabled] = useState(false);С useReducer мы отделяем логику от отображения и делаем код более семантичным.
<button onClick={setIsEnabled(!isEnabled)}>Click Me</button>
...
const [isEnabled, toggle] = useReducer((state) => !state, false);
<button onClick={toggle}>Click Me</button>
Или пример с объектами:
const [user, setUser] = useState({});
return (
<input
onChange={(e) =>
setUser((old) => ({ ...old, name: e.target.value }))
}
value="user.name"
placeholder={"name"}
name={"name"}
/>
);
И вариант с useReducer:const [user, updateUser] = useReducer((oldData, newData) => ({...oldData, ...newData}), {})
return (
<input
onChange={(e) =>
updateUser({ name: e.target.value })
}
value="user.name"
placeholder={"name"}
name={"name"}
/>
);
Сделал сэндбокс поиграться https://codesandbox.io/s/laughing-aryabhata-c9w89m?file=/src/App.js#frontend #react #hooks #state
CodeSandbox
laughing-aryabhata-c9w89m - CodeSandbox
laughing-aryabhata-c9w89m by m.bearlogin using loader-utils, react, react-dom, react-scripts
👍6🔥6😢1
Key в React
Мы привыкли, что key используется только для рендера списков. Но использование key не ограничивается только этим.
Изменение key показывает React что это другой компонент, и необходимо старый размонтировать, а новый замонтировать.
Мы например можем добавить prop key к компоненту формы
Таким образом если userId изменится, то вся форма размонтируется и смонтируется новая форма, и нам не придется обнулять значения формы руками при изменении пользователя.
BEARlogin dev
#react #advices #собеседования
Мы привыкли, что key используется только для рендера списков. Но использование key не ограничивается только этим.
Изменение key показывает React что это другой компонент, и необходимо старый размонтировать, а новый замонтировать.
Мы например можем добавить prop key к компоненту формы
<UserForm key={userId} />Таким образом если userId изменится, то вся форма размонтируется и смонтируется новая форма, и нам не придется обнулять значения формы руками при изменении пользователя.
BEARlogin dev
#react #advices #собеседования
🔥16💯4
setState функция в React
Допустим у нас есть какой то state.
Так вот, setCount не нужно оборачивать в useCallback (некоторые так делают) при передаче его как пропс в дочерний компонент.
React гарантирует, что функция setState не изменится между рендерами.
Так же не нужно добавлять ее в зависимости useEffect, useMemo и useCallback.
Если не верите, то добавьте
Но если я вдруг ошибаюсь, и кейс мемоизации сетера действительно существует, то напишите в комменты :)
BEARlogin dev
#react #advices #собеседования
Допустим у нас есть какой то state.
const [count, setCount] = useState(0);
return <SomeComponent setCount={setCount} />
Так вот, setCount не нужно оборачивать в useCallback (некоторые так делают) при передаче его как пропс в дочерний компонент.
React гарантирует, что функция setState не изменится между рендерами.
Так же не нужно добавлять ее в зависимости useEffect, useMemo и useCallback.
Если не верите, то добавьте
useEffect(() => {
console.log('It has changed!!!!! AAAAAaaaa!!!!11111')
},[setCount])Но если я вдруг ошибаюсь, и кейс мемоизации сетера действительно существует, то напишите в комменты :)
BEARlogin dev
#react #advices #собеседования
👍4
Чистые и нечистые компоненты в React
Деление на чистые компоненты и нечистые контейнеры — это одна из best practice в React, которая помогает сделать код чище и проще в поддержке.
Но следование этому подходу требует дисциплины от разработчика.
Чистые компоненты
Чистые компоненты делают только одно: отображают данные. Они получают всё через props и не хранят никакого состояния. Это их главная сила — такие компоненты легко переиспользовать и тестировать.
Пример:
UserCard не знает, откуда взялись name и age. Ему должно быть всё равно, как эти данные попали в props. Его задача — просто показать их.
Чистые компоненты не должны:
1. Иметь своего состояния или использовать чужое (useState, useSelector и т.д.).
3. Работать с useEffect или другими хуками, которые создают сайд-эффекты.
4. Хранить бизнес-логику.
Да, из-за этого приходится писать больше кода. Но код становится чище.
Нечистые контейнеры
Нечистые контейнеры — это такие "оркестраторы", которые работают с данными: загружают их, хранят в состоянии и передают чистым компонентам. Они могут содержать сайд-эффекты, такие как запросы к API, диспатчинг действий в redux и т.д.
Пример:
Контейнер берёт на себя всю грязную работу: он загружает данные и передаёт их в UserCard. А UserCard продолжает оставаться чистым и ничего не знает про состояние или API.
BEARlogin dev — подпишись!
#react #advices #собеседования
Деление на чистые компоненты и нечистые контейнеры — это одна из best practice в React, которая помогает сделать код чище и проще в поддержке.
Но следование этому подходу требует дисциплины от разработчика.
Чистые компоненты
Чистые компоненты делают только одно: отображают данные. Они получают всё через props и не хранят никакого состояния. Это их главная сила — такие компоненты легко переиспользовать и тестировать.
Пример:
function UserCard({ name, age }) {
return (
<div>
<h2>{name}</h2>
<p>Age: {age}</p>
</div>
);
}UserCard не знает, откуда взялись name и age. Ему должно быть всё равно, как эти данные попали в props. Его задача — просто показать их.
Чистые компоненты не должны:
1. Иметь своего состояния или использовать чужое (useState, useSelector и т.д.).
3. Работать с useEffect или другими хуками, которые создают сайд-эффекты.
4. Хранить бизнес-логику.
Да, из-за этого приходится писать больше кода. Но код становится чище.
Нечистые контейнеры
Нечистые контейнеры — это такие "оркестраторы", которые работают с данными: загружают их, хранят в состоянии и передают чистым компонентам. Они могут содержать сайд-эффекты, такие как запросы к API, диспатчинг действий в redux и т.д.
Пример:
function UserContainer() {
const user = useSelector(state => state.currentUser);
return user ? <UserCard name={user.name} age={user.age} /> : <p>Loading...</p>;
}Контейнер берёт на себя всю грязную работу: он загружает данные и передаёт их в UserCard. А UserCard продолжает оставаться чистым и ничего не знает про состояние или API.
BEARlogin dev — подпишись!
#react #advices #собеседования
🔥7👍1👎1
Когда используется значение, переданное в createContext?
Многие считают, что если
Но это не так.
На самом деле значение, переданное в
Пример:
#react #advices #собеседования
Многие считают, что если
value в провайдере не определен, то используется значение по умолчанию. Но это не так.
На самом деле значение, переданное в
createContext, будет использовано только тогда, когда React не найдёт подходящего провайдера в родителях компонента. Пример:
// Создаём контекст с "default value" как значением по умолчанию
const MyContext = React.createContext("default value");
function MyContextProvider() {
// В провайдере используем состояние с изначальным значением undefined
const [contextValue, setContextValue] = useState(undefined);
return (
<MyContext.Provider value={contextValue}>
<ChildComponent />
<button onClick={() => setContextValue("updated value")}>
Update Context
</button>
</MyContext.Provider>
);
}
function ChildComponent() {
// Используем значение из контекста
const value = useContext(MyContext);
return <p>Value from context: {value}</p>;
}
function App() {
return (
<>
<h1>Without Provider</h1>
<ChildComponent /> {/* value: "default value" */}
<h1>With Provider</h1>
<MyContextProvider>
<ChildComponent />
</MyContextProvider>
{/* value: undefined → "updated value" после нажатия кнопки */}
</>
);
}
#react #advices #собеседования
🔥8👍2
Что происходит в момент, когда мы вызываем setState?
Многие говорят, что обновляется state. Но это не совсем так.
Приведу пример
Работа с функциональными компонентами создаёт иллюзию, будто мы оперируем с императивным подходом: то, что мы видим, — это и есть реальность. Но это лишь фасад. На самом деле React использует декларативный подход.(Я вообще молчу, что у нас count объявлена константой и чисто физически не может изменится)
Что это значит? Это значит, что мы говорим React, какое состояние компонента хотим получить. А дальше начинается магия: React планирует изменения, запускает рендер, и мы не знаем точно, когда состояние действительно обновится и изменения попадут в реальный DOM.
Внутренности процесса
Когда React обновляет дерево компонентов, он делит эту работу на кусочки. Почему? Чтобы уложиться в определённое время — около 16.6 мс на кадр при 60 fps. Если React не успевает, он приостанавливает процесс и продолжает позже.
Но на этом всё не заканчивается. Когда рендер завершён, React сверяет новое дерево с предыдущим (reconciliation). Только после этого, одной синхронной задачей, обновляется реальный DOM — это называется "коммит".
Если интересна такая "внутрянка" React ставьте🔥 и я раскрою глубже, как происходит render, сверка, что такое Fiber и т.д.
BEARlogin dev — подпишись!
#react #advices #собеседования
Многие говорят, что обновляется state. Но это не совсем так.
Приведу пример
const [count, setCount] = useState(0)
function updateCount(value) {
setCount(value);
console.log(count); // в этом месте много людей на собесе говорили мне, что console.log выведет значение value
}
Работа с функциональными компонентами создаёт иллюзию, будто мы оперируем с императивным подходом: то, что мы видим, — это и есть реальность. Но это лишь фасад. На самом деле React использует декларативный подход.
Что это значит? Это значит, что мы говорим React, какое состояние компонента хотим получить. А дальше начинается магия: React планирует изменения, запускает рендер, и мы не знаем точно, когда состояние действительно обновится и изменения попадут в реальный DOM.
Внутренности процесса
Когда React обновляет дерево компонентов, он делит эту работу на кусочки. Почему? Чтобы уложиться в определённое время — около 16.6 мс на кадр при 60 fps. Если React не успевает, он приостанавливает процесс и продолжает позже.
Но на этом всё не заканчивается. Когда рендер завершён, React сверяет новое дерево с предыдущим (reconciliation). Только после этого, одной синхронной задачей, обновляется реальный DOM — это называется "коммит".
Если интересна такая "внутрянка" React ставьте
BEARlogin dev — подпишись!
#react #advices #собеседования
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥62👎1
Камрад в коментах упоминул про случай, когда у нас множество обновлений, описанный в доке реакта и который любят спрашивать на собесах.
У нас есть функция которая вызывает последовательно обновления state.
Вопрос: чему в итоге будет равен count и сколько раз будет вызван render?
Чтобы разобраться в этом, нужно понять как вообще планируются обновления.
Такие вызовы — это тоже самое, что написать setCount(0 + 1) три раза.
Очередь обновлений можно упрощенно показать так (подробней эту тему раскрою в постах про Fiber)
И когда React переходит к фазе рендеринга, он проходит по этом списку и применяет count равным 1 все три раза.
В итоге рендер будет вызван 1 раз, а count = 1
Но если мы применим функциональные обновления
То очередь обновлений будет выглядеть так
Во время рендеринга:
Первое обновление: count = 0 + 1 = 1.
Второе обновление: count = 1 + 1 = 2.
Третье обновление: count = 2 + 1 = 3.
В итоге render будет вызван всегда 1 раз в этих случаях, но в функции обновления мы будем всегда получать результат предыдущего обновления в параметры функции и в таком случае инкремент будет работать правильно.
Другой вопрос, что будет если обновлений запланируется, ну скажем 100 000 сразу. Такой случай рассмотрю в следующих постах.
ставьте🔥 если зашло :)
BEARlogin dev — подпишись!
#react #advices #собеседования
У нас есть функция которая вызывает последовательно обновления state.
const [count, setCount] = useState(0);
const handleClick = () => {
setCount(count + 1);
setCount(count + 1);
setCount(count + 1);
};
Вопрос: чему в итоге будет равен count и сколько раз будет вызван render?
Чтобы разобраться в этом, нужно понять как вообще планируются обновления.
Такие вызовы — это тоже самое, что написать setCount(0 + 1) три раза.
Очередь обновлений можно упрощенно показать так (подробней эту тему раскрою в постах про Fiber)
baseQueue = {
action: 1,
next: {
action: 1,
next: {
action: 1
}
}
}И когда React переходит к фазе рендеринга, он проходит по этом списку и применяет count равным 1 все три раза.
В итоге рендер будет вызван 1 раз, а count = 1
Но если мы применим функциональные обновления
setCount((prev) => prev + 1);
setCount((prev) => prev + 1);
setCount((prev) => prev + 1);
То очередь обновлений будет выглядеть так
baseQueue = {
action: (prev) => prev + 1,
next: {
action: (prev) => prev + 1,
next: {
action: (prev) => prev + 1
}
}
}Во время рендеринга:
Первое обновление: count = 0 + 1 = 1.
Второе обновление: count = 1 + 1 = 2.
Третье обновление: count = 2 + 1 = 3.
В итоге render будет вызван всегда 1 раз в этих случаях, но в функции обновления мы будем всегда получать результат предыдущего обновления в параметры функции и в таком случае инкремент будет работать правильно.
Другой вопрос, что будет если обновлений запланируется, ну скажем 100 000 сразу. Такой случай рассмотрю в следующих постах.
ставьте
BEARlogin dev — подпишись!
#react #advices #собеседования
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥30
Еременко Павел Андреевич.pdf
41.3 KB
Помогите Паше найти работу
Ребят, бро ищет работу фронтом или фулстеком в React или React+NodeJs в целом по хардам крепкий джун, но при этом хорошо решает бизнес задачи, есть аналитическое мышление.
Кому не сложно, закиньте вашим HR, поможем всем миром, как говориться :)
ЛС Паши @eremenko_pa
#frontend #react #nodejs #nestjs #резюмешка
Ребят, бро ищет работу фронтом или фулстеком в React или React+NodeJs в целом по хардам крепкий джун, но при этом хорошо решает бизнес задачи, есть аналитическое мышление.
Кому не сложно, закиньте вашим HR, поможем всем миром, как говориться :)
ЛС Паши @eremenko_pa
#frontend #react #nodejs #nestjs #резюмешка
👍3
Зачем нужен useSyncExternalStore
Вопреки расхожему мнению, оно нужно не только для подключения внешних стейт-менеджеров.
Эта штука в целом работает с внешними источниками состояний.
Что такое этот источник состояния? В целом интерфейс евойный состоит издвух трех функций:
1. subsribe - которая используется, чтобы подписаться на изменение чегобытонибыло
2. getSnapshot - которая используется, чтобы получить то самое чтобытонибыло
3. getServerSnapshot - которая используется, чтобы это самое чтобытонибыло на стороне сервере
При ближайшем рассмотрении весьма и весьма полезная штукенция...
Рассмотрим пример с созданием хука для отслеживания изменения ширины окна
Или вот восхитительная тема с mediaQuery
А в чем разница под капотом? Онакак суслик, ее не видно, но она есть.
1. Поддержка Concurrent Rendering — гарантирует согласованность состояния даже при приостановке или перезапуске рендера.
2. Мгновенная синхронизация — состояние всегда актуально на момент рендера, без задержек, свойственных setState.
3. Меньше лишних ререндеров — React сравнивает значения из getSnapshot и вызывает рендер только при изменении.
4. Поддержка SSR и гидрации — позволяет задать серверное состояние через getServerSnapshot, устраняя расхождения между сервером и клиентом.
В общем, интересная тема, на мой взгляд, нужно брать!
Подготовлю к собесам, помогу с рабочими задачами и росту хардов/софтов. Уперся в потолок с з/п, ответственностью?
Если необходимо менторство - пишите @bearlogin
BEARlogin dev — подпишись!
#собеседования #react
Вопреки расхожему мнению, оно нужно не только для подключения внешних стейт-менеджеров.
Эта штука в целом работает с внешними источниками состояний.
Что такое этот источник состояния? В целом интерфейс евойный состоит из
1. subsribe - которая используется, чтобы подписаться на изменение чегобытонибыло
2. getSnapshot - которая используется, чтобы получить то самое чтобытонибыло
3. getServerSnapshot - которая используется, чтобы это самое чтобытонибыло на стороне сервере
При ближайшем рассмотрении весьма и весьма полезная штукенция...
Рассмотрим пример с созданием хука для отслеживания изменения ширины окна
//Без useSyncExternalStore
function useWindowWidth() {
const [width, setWidth] = useState(window.innerWidth);
useEffect(() => {
const handleResize = () => setWidth(window.innerWidth);
window.addEventListener("resize", handleResize);
return () => window.removeEventListener("resize", handleResize);
}, []);
}
export default function WindowWidthComponent() {
const width = useWindowWidth();
return <div>Ширина окна: {width}px</div>;
}
//Вариант с useSyncExternalStore
import { useSyncExternalStore } from "react";
function useWindowWidth() {
// Подписка на изменения
const subscribe = (callback) => {
window.addEventListener("resize", callback);
return () => window.removeEventListener("resize", callback);
};
// Читаем текущее состояние
const getSnapshot = () => window.innerWidth;
return useSyncExternalStore(subscribe, getSnapshot);
}
export default function WindowWidthComponent() {
const width = useWindowWidth();
return <div>Ширина окна: {width}px</div>;
}
Или вот восхитительная тема с mediaQuery
import { useSyncExternalStore } from "react";
function useMediaQuery(query) {
const mediaQuery= window.matchMedia(query);
const subscribe = (callback) => {
mediaQuery.addEventListener("change", callback);
return () => mediaQuery.removeEventListener("change", callback);
};
const getSnapshot = () => mediaQuery.matches;
return useSyncExternalStore(subscribe, getSnapshot);
}
export default function MediaQueryComponent() {
const isLargeScreen = useMediaQuery("(min-width: 1024px)");
return (
<div>
{isLargeScreen ? "Большой экран" : "Маленький экран"}
</div>
);
}А в чем разница под капотом? Она
1. Поддержка Concurrent Rendering — гарантирует согласованность состояния даже при приостановке или перезапуске рендера.
2. Мгновенная синхронизация — состояние всегда актуально на момент рендера, без задержек, свойственных setState.
3. Меньше лишних ререндеров — React сравнивает значения из getSnapshot и вызывает рендер только при изменении.
4. Поддержка SSR и гидрации — позволяет задать серверное состояние через getServerSnapshot, устраняя расхождения между сервером и клиентом.
В общем, интересная тема, на мой взгляд, нужно брать!
Подготовлю к собесам, помогу с рабочими задачами и росту хардов/софтов. Уперся в потолок с з/п, ответственностью?
Если необходимо менторство - пишите @bearlogin
BEARlogin dev — подпишись!
#собеседования #react
🔥9
Zustand подписка только на конкретные изменения стора
Если вам нужно подписаться на изменение какой то части стора, то используйте миддлварь subscribeWithSelector
Теперь подписка сработает только при изменении count, а изменения user её не триггерят.
--
Подготовлю к собесам, помогу с рабочими задачами и росту хардов/софтов. Уперся в потолок с з/п, ответственностью? Помогу с ростом грейда от миддла до синьора.
Если необходимо менторство - пишите @bearlogin
BEARlogin dev — подпишись!
#react #zustand
Если вам нужно подписаться на изменение какой то части стора, то используйте миддлварь subscribeWithSelector
import { create } from "zustand";
import { subscribeWithSelector } from "zustand/middleware";
const useStore = create(
subscribeWithSelector((set) => ({
count: 0,
user: { name: "Alice", age: 25 },
increment: () => set((state) => ({ count: state.count + 1 })),
}))
);
// Подписка ТОЛЬКО на `count`
useStore.subscribe(
(state) => state.count,
(newCount, prevCount) => {
console.log(`Счётчик изменился: ${prevCount} → ${newCount}`);
}
);Теперь подписка сработает только при изменении count, а изменения user её не триггерят.
--
Подготовлю к собесам, помогу с рабочими задачами и росту хардов/софтов. Уперся в потолок с з/п, ответственностью? Помогу с ростом грейда от миддла до синьора.
Если необходимо менторство - пишите @bearlogin
BEARlogin dev — подпишись!
#react #zustand
👍3🔥3