- Оригинальный адрес:Redux vs. The React Context API
- Оригинальный автор:Dave Ceddia
- Перевод с:Программа перевода самородков
- Постоянная ссылка на эту статью:GitHub.com/rare earth/gold-no…
- Переводчик:Xuyuey
- Корректор:Minghao, Baddyo
React представил новый Context API в версии 16.3 — скажем такновыйПотому чтостарая версияContext API — это экспериментальная фича за кулисами, и большинство людей либо не знают о ней, либо стараются избегать ее использования в соответствии с официальной документацией.
Однако теперь Context API стал первоклассным гражданином в React, открытым для всех (не так, как раньше, за что сейчас ратуют официально).
Как только была выпущена версия 16.3 React, Интернет заполонили статьи, утверждающие, что новый Context API победит Redux. Но если вы спросите Redux, я думаю, он скажет: «Сообщения о том, что я умру, действительнопреувеличенный".
В этом посте я хочу рассказать вам, как работает новый Context API, чем он похож на Redux и когда использовать Context API.вместоRedux и почему Context API не во всех случаях заменяет Redux.
Если вам просто нужен обзор контекста, вы можетеперейти в этот раздел.
Простой пример Реакта
Предполагается, что вы уже знакомы с основами React (реквизит и состояние), но если нет, вы можете пройти мой 5-дневный бесплатный курс, чтобы изучить основы React.
Давайте рассмотрим пример, который поможет большинству людей освоить Redux. Мы начнем с чистой версии React, затем посмотрим, как она выглядит в Redux, и, наконец, с Context.
Информация о пользователе отображается в приложении в двух местах: в правом верхнем углу панели навигации и в боковой панели рядом с основным контентом.
(Вы могли заметить, что это очень похоже на Twitter. Это определенно не совпадение! Один из лучших способов отточить свои навыки React — этоКопировать — создать копию существующего приложения.).
Структура компонентов выглядит следующим образом:
С чистым React (просто обычные реквизиты) нам нужно хранить информацию о пользователях достаточно высоко в дереве компонентов, чтобы мы могли передавать ее каждому компоненту, который в ней нуждается. В нашем случае информация о пользователе должна храниться вApp
середина.
Затем, чтобы передать информацию о пользователе компонентам, которым она нужна, приложение должно сначала передать ее в Nav и Body. Потом,опять такиПерейдите к UserAvatar (ура! Наконец-то он здесь) и боковой панели. Наконец, боковая панель должна снова передать его в UserStats.
Посмотрим, как работает код (я сложил все в один файл для удобства чтения, но на самом деле это может бытькакая-то стандартная структурана несколько файлов).
import React from "react";
import ReactDOM from "react-dom";
import "./styles.css";
const UserAvatar = ({ user, size }) => (
<img
className={`user-avatar ${size || ""}`}
alt="user avatar"
src={user.avatar}
/>
);
const UserStats = ({ user }) => (
<div className="user-stats">
<div>
<UserAvatar user={user} />
{user.name}
</div>
<div className="stats">
<div>{user.followers} Followers</div>
<div>Following {user.following}</div>
</div>
</div>
);
const Nav = ({ user }) => (
<div className="nav">
<UserAvatar user={user} size="small" />
</div>
);
const Content = () => <div className="content">main content here</div>;
const Sidebar = ({ user }) => (
<div className="sidebar">
<UserStats user={user} />
</div>
);
const Body = ({ user }) => (
<div className="body">
<Sidebar user={user} />
<Content user={user} />
</div>
);
class App extends React.Component {
state = {
user: {
avatar:
"https://www.gravatar.com/avatar/5c3dd2d257ff0e14dbd2583485dbd44b",
name: "Dave",
followers: 1234,
following: 123
}
};
render() {
const { user } = this.state;
return (
<div className="app">
<Nav user={user} />
<Body user={user} />
</div>
);
}
}
ReactDOM.render(<App />, document.querySelector("#root"));
Ознакомьтесь с онлайн-примерами в CodeSandbox.
это здесь,App
инициализировать состояниеуже включает объект «пользователь», но в реальном приложении вам может понадобитьсяПолучить эти данные с сервераи сохраните его в состоянии для рендеринга.
Этот способ опорного бурения неУпсспособ сделать. Это работает просто отлично. Не во всех случаях поощряется «поддерживающее сверление» — это вполне допустимый паттерн, который лежит в основе работы React. Но если компоненты слишком глубокие, это может немного раздражать при их написании. Особенно, когда вы передаете не одно свойство, а целую кучу, это становится еще более раздражающим.
Однако у этой стратегии «пропорного бурения» есть больший недостаток: она объединяет компоненты, которые должны быть независимыми. В приведенном выше примереNav
Компонент должен получить свойство «user» и передать его вUserAvatar
,хотяNav
больше нигде вuser
Атрибуты.
Тесно связанные компоненты (например, те, которые передают свойства своим дочерним компонентам) труднее использовать повторно, потому что всякий раз, когда вы используете их в новом месте, вы должны связать их с новым родительским компонентом.
Посмотрим, как улучшить.
Прежде чем использовать Context или Redux...
Если вы можете найти способсливатьсяструктуру приложения и воспользоваться преимуществамиchildren
свойства, так что вам не нужно прибегать к глубокому бурениюИли Контекст, или Редукс, вы также можете сделать структуру кода более понятной.
Для тех компонентов, которым требуются общие заполнители, например, в этом примереNav
,Sidebar
а такжеBody
, детская собственность является хорошим решением. Также знайте, что вы можете передавать элементы JSX вЛюбыеСвойства, а не только «дочерние элементы» — так что имейте это в виду, если вы хотите использовать более одного «слота» для вставки компонентов.
В этом примереNav
,Sidebar
а такжеBody
Получайте дочерние элементы и визуализируйте их по мере их появления. Таким образом, пользователю компонента не нужно беспокоиться о конкретных данных, передаваемых компоненту — ему просто нужно использовать данные, определенные в компоненте, и просто визуализировать компонент так, как он изначально требовался компонентом. В этом примере также показано, как использоватьЛюбыеСобственность проходит детей.
(Спасибо Дэну Абрамовуэто предложение! )
import React from "react";
import ReactDOM from "react-dom";
import "./styles.css";
const UserAvatar = ({ user, size }) => (
<img
className={`user-avatar ${size || ""}`}
alt="user avatar"
src={user.avatar}
/>
);
const UserStats = ({ user }) => (
<div className="user-stats">
<div>
<UserAvatar user={user} />
{user.name}
</div>
<div className="stats">
<div>{user.followers} Followers</div>
<div>Following {user.following}</div>
</div>
</div>
);
// 接收并渲染 children
const Nav = ({ children }) => (
<div className="nav">
{children}
</div>
);
const Content = () => (
<div className="content">main content here</div>
);
const Sidebar = ({ children }) => (
<div className="sidebar">
{children}
</div>
);
// Body 需要一个 sidebar 和 content,但是可以按照这样的方式写,
// 它们可以是任意属性
const Body = ({ sidebar, content }) => (
<div className="body">
<Sidebar>{sidebar}</Sidebar>
{content}
</div>
);
class App extends React.Component {
state = {
user: {
avatar:
"https://www.gravatar.com/avatar/5c3dd2d257ff0e14dbd2583485dbd44b",
name: "Dave",
followers: 1234,
following: 123
}
};
render() {
const { user } = this.state;
return (
<div className="app">
<Nav>
<UserAvatar user={user} size="small" />
</Nav>
<Body
sidebar={<UserStats user={user} />}
content={<Content />}
/>
</div>
);
}
}
ReactDOM.render(<App />, document.querySelector("#root"));
Ознакомьтесь с онлайн-примерами в CodeSandbox.
Если ваше приложение слишком сложное (сложнее, чем этот пример!), может быть трудно понять, как настроитьchildren
модель. Давайте посмотрим, как заменить винтовое сверление на Redux.
Пример использования Redux
Я кратко рассмотрю пример Redux здесь, чтобы мы могли потратить немного больше времени на изучение того, как работает Context, поэтому, если вы не очень хорошо знаете Redux, вы можете сначала посмотреть мойВведение в Редукс(илисмотреть видео).
Мы все еще используем вышеупомянутое приложение React, здесь мы рефакторим его до версии Redux.user
Информация перемещается в хранилище Redux, что означает, что мы можем использовать react-reduxconnect
функция, непосредственноuser
Свойство внедряется в компонент, который в нем нуждается.
Это огромная победа в развязке. посмотриNav
,Sidebar
а такжеBody
, вы обнаружите, что они больше не получают и не передаютuser
характеристики. Хватит играть с горячим картофелем реквизита. Разумеется, лишней связи тоже не будет.
Редуктор здесь не делает много работы, он довольно прост. У меня есть больше об этом в другом местеКак работают редукторы Reduxтак же какКак написать в нем неизменяемый кодВы можете ознакомиться со статьей.
import React from "react";
import ReactDOM from "react-dom";
// 我们需要 createStore、connect 和 Provider:
import { createStore } from "redux";
import { connect, Provider } from "react-redux";
// 创建一个初始 state 为空的 reducer
const initialState = {};
function reducer(state = initialState, action) {
switch (action.type) {
// 响应 SET_USER 行为并更新
// 相应的 state
case "SET_USER":
return {
...state,
user: action.user
};
default:
return state;
}
}
// 使用 reducer 创建 store
const store = createStore(reducer);
// 触发设置 user 的行为
// (因为 user 初始化时为空)
store.dispatch({
type: "SET_USER",
user: {
avatar: "https://www.gravatar.com/avatar/5c3dd2d257ff0e14dbd2583485dbd44b",
name: "Dave",
followers: 1234,
following: 123
}
});
// 函数 mapStateToProps 从 state 对象中提取 user 值
// 并将它作为 `user` 属性传递
const mapStateToProps = state => ({
user: state.user
});
// connect() UserAvatar 以便它可以直接接收 `user` 属性,
// 而无需从上层组件中获取
// 也可以把它分成下面 2 个变量:
// const UserAvatarAtom = ({ user, size }) => ( ... )
// const UserAvatar = connect(mapStateToProps)(UserAvatarAtom);
const UserAvatar = connect(mapStateToProps)(({ user, size }) => (
<img
className={`user-avatar ${size || ""}`}
alt="user avatar"
src={user.avatar}
/>
));
// connect() UserStats 以便它可以直接接收 `user` 属性,
// 而无需从上层组件中获取
// (同样使用 mapStateToProps 函数)
const UserStats = connect(mapStateToProps)(({ user }) => (
<div className="user-stats">
<div>
<UserAvatar />
{user.name}
</div>
<div className="stats">
<div>{user.followers} Followers</div>
<div>Following {user.following}</div>
</div>
</div>
));
// Nav 不再需要知道 `user` 属性
const Nav = () => (
<div className="nav">
<UserAvatar size="small" />
</div>
);
const Content = () => (
<div className="content">main content here</div>
);
// Sidebar 也不再需要知道 `user` 属性
const Sidebar = () => (
<div className="sidebar">
<UserStats />
</div>
);
// body 同样不需要知道 `user` 属性
const Body = () => (
<div className="body">
<Sidebar />
<Content />
</div>
);
// App 不再需要保存 state,
// 所以可以把它写成一个无状态组件
const App = () => (
<div className="app">
<Nav />
<Body />
</div>
);
// 用 Provider 包裹整个 App,
// 以便 connect() 可以连接到 store
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.querySelector("#root")
);
Ознакомьтесь с онлайн-примерами в CodeSandbox.
Теперь вам может быть интересно, как Redux может достичь такой удивительной функциональности. "Хочу знать" - это хорошо. React не поддерживает передачу свойств на несколько уровней, так почему Redux это делает?
Ответ в том, что Redux использует Reactcontext(контекст)характеристика. Не тот Context API, о котором мы говорим сейчас (пока), а старый. Это тот, который, как говорят документы React, не используйте, если вы не пишете библиотеку или не знаете, что делаете.
Контекст подобен электронной шине, бегущей за каждым компонентом: чтобы получить мощность (данные), которую он передает, вы просто подключаете его. Принимая во внимание, что (React-) Reduxconnect
Функции делают именно это.
Однако эта особенность Redux — лишь верхушка айсберга. Возможность передавать данные везде — лучшее, что есть в Redux.очевидныйфункция. Вот некоторые другие преимущества, которые вы можете получить из коробки:
connect
Сделайте ваши компоненты чистыми
connect
Подключенные компоненты можно сделать «чистыми», то есть им нужно повторно отображать только при изменении их свойств, то есть при изменении их части состояния Redux. Это предотвращает ненужный повторный рендеринг и обеспечивает быструю работу приложения. Подход «сделай сам»: создайте наследование классовPureComponent
, или реализовать самостоятельноshouldComponentUpdate
.
Простая отладка с Redux
Хотя написание действий и редюсеров немного сложнее, мы можем сбалансировать это с мощными возможностями отладки, которые они нам предоставляют.
использоватьРасширение Redux DevTools, каждое действие, выполняемое приложением, автоматически регистрируется. Вы можете включить его в любое время, чтобы увидеть, какое действие было запущено, какова была полезная нагрузка, а также состояние до и после выполнения действия.
Redux DevTools предоставляет еще одну замечательную функцию —time travel debugging(отладка путешествия во времени), то есть вы можете щелкнуть любое прошедшее действие и перейти к этому моменту времени, и он в основном воспроизводит каждое действие, включая текущее, но исключая действия, которые еще не были запущены. Принцип состоит в том, что каждое действиенеизменныйобновить состояние, так что вы можете получить список записанных обновлений состояния и воспроизвести их, переходя туда, куда вы хотите, без каких-либо побочных эффектов.
И в настоящее время естьLogRocketТакой инструмент можно использовать для каждого из ваших пользователей вПроизводственная средаПостоянно включенный Redux DevTools доступен в . Есть отчет об ошибке? Неважно. Найдите сеанс этого пользователя в LogRocket, и вы увидите все, что он сделал, и что именно вызвало действие. Все это возможно с помощью потока действий Redux.
Настройте Redux с помощью промежуточного программного обеспечения
Поддержка Reduxпромежуточное ПО(middleware), что означает «функция, которая запускается каждый раз, когда отправляется действие». Написание собственного промежуточного программного обеспечения не так сложно, как кажется, и оно может реализовать некоторые мощные функции.
Например……
- хочу назвать каждого
FETCH_
Отправить запрос API в действии в начале? Вы можете использовать промежуточное ПО. - Хотите регистрировать события в одном централизованном месте для своего аналитического программного обеспечения? Промежуточное ПО — хорошее место.
- Хотите, чтобы определенные действия не срабатывали в определенное время? Вы можете сделать это с помощью промежуточного программного обеспечения, и оно прозрачно для остальной части приложения.
- Хотите перехватывать действия с токенами JWT и автоматически сохранять их в localStorage? Да, вы также можете использовать промежуточное ПО.
Вот хорошая статья с некоторымиПример того, как написать промежуточное ПО Redux.
Как использовать контекстный API React
Однако, возможно, вам не нужны все эти причудливые функции Redux. Возможно, вам не нужна простая отладка, настройка или автоматизация повышения производительности — все, что вам нужно, — это легко передавать данные. Может быть, ваше приложение маленькое, или вам просто нужно заставить приложение работать сейчас, а о наворотах подумать позже.
Новый контекстный API React может соответствовать вашим требованиям. Давайте посмотрим, как это работает.
Если вы предпочитаете смотреть видео (продолжительность 3:43), а не читать статью, я разместил короткий курс Context API на Egghead:
В Context API есть 3 важные части:
-
React.createContext
функция: создать контекст -
Provider
(Зависит отcreateContext
назад): строит «электронную шину» в дереве компонентов -
Consumer
(также поcreateContext
возврат): доступ к «электронной шине» для получения данных
здесьProvider
и React-ReduxProvider
очень похожий. он получаетvalue
свойство, это свойство может быть чем угодно (даже магазином Redux... но это глупо). Скорее всего, это будет объект, который включает в себя ваши данные и то, что вы хотите сделать с данными.
здесьConsumer
Работает немного похоже на React-Reduxconnect
Функция, которая получает данные для использования компонентом.
Вот основные моменты:
// 在最开始,我们创建了一个新的上下文
// 它是一个拥有两个属性 { Provider, Consumer } 的对象
// 注意这里用的是 UpperCase 命名,不是 camelCase
// 这很重要,因为我们一会要以组件的方式使用它
// 而组件的名称必须以大写字母开头
const UserContext = React.createContext();
// 下面是需要从上下文中获取数据的组件
// 可以通过使用 UserContext 的 Consumer 属性
// Consumer 使用的是 "render props" 模式
const UserAvatar = ({ size }) => (
<UserContext.Consumer>
{user => (
<img
className={`user-avatar ${size || ""}`}
alt="user avatar"
src={user.avatar}
/>
)}
</UserContext.Consumer>
);
// 注意我们不再需要 'user' 属性了
// 因为 Consumer 可以直接从上下文中获取
const UserStats = () => (
<UserContext.Consumer>
{user => (
<div className="user-stats">
<div>
<UserAvatar user={user} />
{user.name}
</div>
<div className="stats">
<div>{user.followers} Followers</div>
<div>Following {user.following}</div>
</div>
</div>
)}
</UserContext.Consumer>
);
// …… 所有其它的组件 ……
// ……(就是那些不会用到 `user` 的组件)……
// 在最下面,App 的内部
// 我们用 Provider 在整棵树中传递上下文
class App extends React.Component {
state = {
user: {
avatar:
"https://www.gravatar.com/avatar/5c3dd2d257ff0e14dbd2583485dbd44b",
name: "Dave",
followers: 1234,
following: 123
}
};
render() {
return (
<div className="app">
<UserContext.Provider value={this.state.user}>
<Nav />
<Body />
</UserContext.Provider>
</div>
);
}
}
вотПолный пример в CodeSandbox.
Давайте посмотрим, как это работает.
Помните, что есть 3 части: сам контекст (поReact.createContext
create), и два компонента, которые общаются с ним (Provider
а такжеConsumer
).
Поставщик и Потребитель — хорошие друзья
Поставщик и Потребитель связаны вместе. неразлучны. и они умеют толькодругая сторонадиалог. Если вы создаете два отдельных контекста, например «Context1» и «Context2», поставщик и потребитель Context1 не могут взаимодействовать с поставщиком и потребителем Context2.
состояние не сохраняется в контексте
Обратите внимание на контекстнетсобственное государство. Это просто канал для данных. вы должны передать значениеProvider
, то это точное значение передается всем, кто знает, как его получитьConsumer
(Потребитель и поставщик привязаны к одному и тому же контексту).
При создании контекста вы можете передать «значение по умолчанию» следующим образом:
const Ctx = React.createContext(yourDefaultValue);
когдаConsumer
быть помещен в нетProvider
При обертывании дерева оно получит это значение по умолчанию. Если вы не передадите значение по умолчанию, это значение будетundefined
. Но обратите внимание, что это значение по умолчанию, а не начальное значение. Контекст ничего не содержит, он просто распределяет данные, которые вы передаете.
Потребитель использует режим Render Props
Редуксconnect
Функция — это компонент более высокого порядка (или сокращенно HoC). Этопакетдругой компонент и передать ему реквизиты.
контекстуальныйConsumer
Вместо этого он ожидает, что дочерний компонент будет функцией. Затем он вызывает эту функцию при рендеринге, удаляя ее из упаковкиProvider
(или значение контекста по умолчанию, если вы не передали значение по умолчанию, это также может бытьundefined
) дочернему компоненту.
Провайдер принимает одно значение
он получаетvalue
свойство, только это одно значение. Но помните, что это значение может быть любым. На практике, если вы хотите передать несколько значений, вы должны создать объект, содержащий эти значения, а затемэтот объектпередай.
Это почти ядро Context API.
Гибкий контекстный API
Поскольку создание контекста дает нам два компонента для использования (поставщик и потребитель), мы можем использовать их по своему усмотрению. Вот несколько идей.
Превратите Consumer в компонент более высокого порядка
не люблю использовать в каждой потребностиUserContext.Consumer
где добавить его использование? Ну, вот ваш код! Ты можешь делать что захочешь. Вы взрослый.
Если вы предпочитаете получать значение как свойство, вы можете указатьConsumer
Напишите обертку следующим образом:
function withUser(Component) {
return function ConnectedComponent(props) {
return (
<UserContext.Consumer>
{user => <Component {...props} user={user}/>}
</UserContext.Consumer>
);
}
}
Затем вы можете переписать свой код, например, используя новыйwithUser
функциональныйUserAvatar
Компоненты:
const UserAvatar = withUser(({ size, user }) => (
<img
className={`user-avatar ${size || ""}`}
alt="user avatar"
src={user.avatar}
/>
));
БУМ, контекст может быть как у Reduxconnect
Работайте так. Сделайте ваши компоненты чистыми.
вотПример CodeSandbox с этим компонентом более высокого порядка.
Сохранить состояние с провайдером
Помните, что Provider контекста — это просто конвейер. Он не хранит никаких данных. Но это не мешает вам делатьСобственныйоболочка для хранения данных.
В приведенном выше примере я используюApp
Данные сохраняются, поэтому единственная новая вещь, о которой вам нужно знать, — это компонент Provider + Consumer. Но, может быть, вы хотите написать свой собственный «магазин» и т. д. Вы можете создать компонент для хранения данных и передачи их через контекст.
class UserStore extends React.Component {
state = {
user: {
avatar:
"https://www.gravatar.com/avatar/5c3dd2d257ff0e14dbd2583485dbd44b",
name: "Dave",
followers: 1234,
following: 123
}
};
render() {
return (
<UserContext.Provider value={this.state.user}>
{this.props.children}
</UserContext.Provider>
);
}
}
// ……略过中间的内容……
const App = () => (
<div className="app">
<Nav />
<Body />
</div>
);
ReactDOM.render(
<UserStore>
<App />
</UserStore>,
document.querySelector("#root")
);
Теперь ваши пользовательские данные содержатся в отдельном компоненте, этот компонентТолькоОсновное внимание уделяется пользовательским данным. отличный.App
Можно снова стать компонентом без гражданства. Мне кажется, аккуратнее.
вотПример CodeSandbox с этим UserStore.
Передача действий через контекст
Помните, что объект, передаваемый через Provider, может содержать все, что вы хотите. Это означает, что он может содержать функции. Можно даже назвать это «действием».
Вот новый пример: простая комната с переключателем, который переключает цвет фона — извините, я имел в виду свет.
Состояние сохраняется в магазине, а также в магазине есть функции переключения света. И состояние, и функции передаются через контекст.
import React from "react";
import ReactDOM from "react-dom";
import "./styles.css";
// 简单的空上下文
const RoomContext = React.createContext();
// 一个组件
// 唯一的工作就是管理 Room 的 state
class RoomStore extends React.Component {
state = {
isLit: false
};
toggleLight = () => {
this.setState(state => ({ isLit: !state.isLit }));
};
render() {
// 传递 state 和 onToggleLight 操作
return (
<RoomContext.Provider
value={{
isLit: this.state.isLit,
onToggleLight: this.toggleLight
}}
>
{this.props.children}
</RoomContext.Provider>
);
}
}
// 从 RoomContext 中接收灯光的 state
// 以及切换灯光的函数
const Room = () => (
<RoomContext.Consumer>
{({ isLit, onToggleLight }) => (
<div className={`room ${isLit ? "lit" : "dark"}`}>
The room is {isLit ? "lit" : "dark"}.
<br />
<button onClick={onToggleLight}>Flip</button>
</div>
)}
</RoomContext.Consumer>
);
const App = () => (
<div className="app">
<Room />
</div>
);
// 用 RoomStore 包裹整个 App
// 它可以像在 `App` 内那样工作
ReactDOM.render(
<RoomStore>
<App />
</RoomStore>,
document.querySelector("#root")
);
вотПолный пример в CodeSandbox.
Должен ли я использовать Context или Redux?
Теперь, когда вы увидели оба способа, какой из них следует использовать? Что ж, вот одна вещь, которая сделает ваше приложениелучшеа такжевеселее писать,То естьпринять решение. Я знаю, что вы, вероятно, просто хотите "ответ", но мне жаль говорить вам, "это зависит".
Это зависит от того, насколько большим будет ваше приложение. Сколько человек будет задействовано — только вы или большая команда? Ваш опыт или опыт вашей команды с функциональными концепциями, на которые опирается Redux, такими как неизменяемость и чистые функции.
Огромное порочное заблуждение, которое существует в экосистеме JavaScript, состоит в том, чтоконкурироватьКонцепция чего-либо. Утверждается, что каждый выбор — это игра с нулевой суммой; если вы используетеБиблиотека А, вы не можете использоватьего конкурентная библиотека B. Идея состоит в том, что когда появляется новая библиотека, которая в чем-то лучше, она должна заменить существующую библиотеку. Это ощущение "или... или...", когда вы должны выбрать лучшую библиотеку или использовать предыдущую библиотеку с кем-то из прошлого.
Лучший способ - иметь такой, как вашящик для инструментовТо же самое, вы можете поместить в него все свои варианты. Это все равно, что выбрать отвертку или ударную дрель. При выполнении 80% работы перфоратор закручивает винт быстрее, чем отвертка. Но для остальных 20% отвертка на самом деле является лучшим вариантом — возможно, потому, что места мало или предмет хрупкий. Когда у меня есть ударная дрель, я не выбрасываю сразу ни отвертку, ни даже безударную дрель. ударная дрель нетзаменятьОни просто дали мне еще один вариант. Еще один способ решения проблемы.
React «заменит» Angular или jQuery, но Context не «заменит» Redux таким образом. Черт возьми, я до сих пор использую jQuery, когда мне нужно что-то сделать быстро. Я до сих пор иногда использую шаблоны EJS, отображаемые на сервере, вместо всего приложения React. Иногда React больше, чем поставленная задача. Иногда в Redux есть функции, которые вам не нужны.
Теперь, когда Redux превышает ваши потребности, вы можете использовать Context.
переводить
- Russian(Предоставлено Максимом Ващенко)
- Japanese(Предоставлено Киичи)
- Portuguese(С любезного разрешения Вендерсона Пиреса)
Если вы обнаружите ошибки в переводе или в других областях, требующих доработки, добро пожаловать наПрограмма перевода самородковВы также можете получить соответствующие бонусные баллы за доработку перевода и PR. начало статьиПостоянная ссылка на эту статьюЭто ссылка MarkDown этой статьи на GitHub.
Программа перевода самородковэто сообщество, которое переводит высококачественные технические статьи из Интернета сНаггетсДелитесь статьями на английском языке на . Охват контентаAndroid,iOS,внешний интерфейс,задняя часть,блокчейн,товар,дизайн,искусственный интеллектЕсли вы хотите видеть более качественные переводы, пожалуйста, продолжайте обращать вниманиеПрограмма перевода самородков,официальный Вейбо,Знай колонку.