Автор оригинала: TK.
После семи лет разработки полного стека с использованием Ruby, Python и Vanilla JavaScript, в эти дни я в основном работаю с JavaScript, Tymdercript, React и Redux.
Сообщество JavaScript отлично и движется очень быстро. Тонны вещей создаются «ночь», обычно образно, но иногда буквально. Все это заставляет, что это действительно трудно поддерживать в курсе.
Я всегда чувствую, что я опоздал на вечеринку JavaScript. И я хочу быть там, хотя я не очень люблю вечеринки.
Только один год работы с реагированием и redux И я чувствовал, что мне нужно было узнать новые, такие как крючки, а контекст API для управления состоянием. Прочитав некоторые статьи об этом, я хотел попробовать эти концепции, поэтому я создал простой проект в качестве лаборатории для экспериментов с теми.
Так как я был маленьким мальчиком, я увлечен покемоном. Всегда было весело играть в игры в игровом мальчике и покорив все лиги. Теперь как разработчик, я хочу играть с Pokémon API Отказ
Я решил построить простую веб-страницу, где я смогу делиться данными между разными частями страницы. Страница будет иметь три основных раздела:
- Коробка со списком всех существующих покемонов
- Коробка со списком всех захваченных покемонов
- Коробка с входом, чтобы добавить новый покемон в список
И каждая коробка будет иметь следующее поведение или действия:
- Для каждого покемона в первом поле я могу запечатлеть их и отправить на вторую коробку
- Для каждого покемона во второй коробке я могу отпустить их и отправлять на первую коробку
- Как игра Бога, я могу создать покемон, заполнив ввод и отправляю их в первую коробку
Таким образом, все функции, которые я хотел реализовать, были четкими – списки и действиями.
Листинг покемонов
Основная особенность, которую я хотел построить первым, был список покемонов. Так что для массива объектов я хотел перечислить и показать имя атрибут каждого объекта.
Я начал с первого коробки: существующий покемон.
Сначала я подумал, что мне не нужен Pokémon API – я мог бы просто изменить список и посмотреть, работает ли это. С Уместите Я могу объявить свое состояние своего компонента и использовать его.
Мы определяем его с величием по умолчанию списком покемонов Mock, просто чтобы проверить его:
const [pokemons] = useState([
{ id: 1, name: 'Bulbasaur' },
{ id: 2, name: 'Charmander' },
{ id: 3, name: 'Squirtle' }
]);
Здесь у нас есть список трех объектов покемонов. Уместите Крюк обеспечивает пару элементов: текущее состояние и функция, позволяющая обновить это созданное состояние.
Теперь с состоянием покемона мы можем сопоставить его и сделать имя каждого.
{pokemons.map((pokemon) => {pokemon.name}
)}
Это просто карта, возвращая каждое имя покемона в тег абзаца.
Это весь компонент реализован:
import React, { useState } from 'react';
const PokemonsList = () => {
const [pokemons] = useState([
{ id: 1, name: 'Bulbasaur' },
{ id: 2, name: 'Charmander' },
{ id: 3, name: 'Squirtle' }
]);
return (
Pokemons List
{pokemons.map((pokemon) =>
{pokemon.id}
{pokemon.name}
)}
)
}
export default PokemonsList;
Просто немного твик здесь:
- Я добавил
ключВ сочетании покемоновIDиимя - И я также оказал абзац для
IDатрибут (я просто проверил его. Но мы удалим это позже.)
Большой! Теперь у нас есть первый список вверх и работает.
Я хочу сделать это же реализацию, но теперь для захваченного покемона. Но для захваченного покемонов я сначала хочу создать пустой список, потому что, когда начинается «игра», у меня не будет захваченных покемонов, верно? Верно!
const [pokemons] = useState([]);
Вот и все, действительно просто!
Весь компонент выглядит похоже на другой:
import React, { useState } from 'react';
const CapturedPokemons = () => {
const [pokemons] = useState([]);
return (
Captured Pokemons
{pokemons.map((pokemon) =>
{pokemon.id}
{pokemon.name}
)}
)
}
export default CapturedPokemons;
Здесь мы используем карта , но как массив пуст, он ничего не делает.
Теперь, когда у меня есть два основных компонента, я могу использовать их вместе в Приложение составная часть:
import React from 'react'; import './App.css'; import PokemonsList from './PokemonsList'; import Pokedex from './Pokedex'; const App = () => (); export default App;
Захват и выпуск
Это вторая часть нашего приложения, где мы можем захватить и выпустить покемонов. Итак, давайте перейдем на ожидаемое поведение.
Для каждого покемона в списке доступных покемонов я хочу включить действие для их захвата. Действие захвата удалит их из списка, где они были и добавили их в список захваченных покемонов.
Действие выпуска будет иметь подобное поведение. Но вместо того, чтобы переходить из доступного списка в захваченный список, это будет обратное. Мы переместим их из захваченного списка в доступный список.
Таким образом, оба ящика должны делиться данными, чтобы иметь возможность добавлять покемонов в другой список. Как мы это делаем, так как они разные компоненты в приложении? Давайте поговорим о API React Context.
Контекст API был разработан для создания глобальных данных для определенного дерева компонентов реагирования. Поскольку данные глобальные, мы можем поделиться его среди компонентов в этом определенном дереве. Итак, давайте будем использовать его, чтобы поделиться нашими простыми данными покемонов между двумя коробками.
Ментальное примечание: «Контекст в основном используется, когда некоторые данные должны быть доступны многими компонентами на разных уровнях вложения». – Реагистрировать документы.
Используя API, мы просто создаем новый контекст, как это:
import { createContext } from 'react';
const PokemonContext = createContext();
Теперь, с PokemonContext мы можем использовать его поставщик. Он будет работать как компонент обертки дерева компонентов. Он предоставляет глобальные данные этих компонентов и позволяет им подписаться на любые изменения, связанные с этим контекстом. Похоже, это выглядит:
ценность Программа – это просто значение, что этот контекст предоставляет обернутые компоненты. Что мы должны предоставить доступным и захваченным спискам?
Покемоны: Чтобы перечислить в доступном спискеCaptedPokemons: в список в захваченном спискеSetPokemons: Чтобы иметь возможность обновить доступный списокsetcapturedpokemons: Чтобы иметь возможность обновить захваченный список
Как я уже упоминал ранее в Уместите Часть, этот крючок всегда предоставляет пару: состояние и функцию для обновления этого состояния. Эта функция обрабатывает и обновляет контекстное состояние. Другими словами, они являются SetPokemons и setcapturedpokemons Отказ Как?
const [pokemons, setPokemons] = useState([
{ id: 1, name: 'Bulbasaur' },
{ id: 2, name: 'Charmander' },
{ id: 3, name: 'Squirtle' }
]);
Теперь у нас есть SetPokemons Отказ
const [capturedPokemons, setCapturedPokemons] = useState([]);
И теперь у нас также есть setcapturedpokemons Отказ
Со всеми этими значениями в руке мы можем пройти их к поставщику ценность пропры
import React, { createContext, useState } from 'react';
export const PokemonContext = createContext();
export const PokemonProvider = (props) => {
const [pokemons, setPokemons] = useState([
{ id: 1, name: 'Bulbasaur' },
{ id: 2, name: 'Charmander' },
{ id: 3, name: 'Squirtle' }
]);
const [capturedPokemons, setCapturedPokemons] = useState([]);
const providerValue = {
pokemons,
setPokemons,
capturedPokemons,
setCapturedPokemons
};
return (
{props.children}
)
};
Я создал PokemonProvider Чтобы обернуть все эти данные и API для создания контекста и вернуть поставщика контекста с определенным значением.
Но как мы предоставляем все эти данные и API для компонента? Нам нужно сделать две основные вещи:
- Оберните компоненты в этот поставщик контекста
- Используйте контекст в каждом компонент
Давайте сначала обернуть их:
const App = () => ();
И мы используем контекст, используя упреждающий текст и прохождение созданного PokemonContext Отказ Нравится:
import { useContext } from 'react';
import { PokemonContext } from './PokemonContext';
useContext(PokemonContext); // returns the context provider value we created
Мы хотим иметь возможность поймать доступных покемонов, поэтому было бы полезно иметь setcapturedpokemons Функция API обновить захваченный покемон.
Поскольку каждый Pokémon захвачен, нам нужно удалить его из доступного списка. SetPokemons Также нужно здесь. А для обновления каждого списка нам нужны текущие данные. Так что в основном нам нужно все, от контекста поставщика.
Нам нужно создать кнопку с действием для захвата покемонов:
<кнопка>Тег сOnClickПризываязахватфункция и передача покемонов
-
захватФункция обновитПокемоныиCaptedPokemonsсписки
const capture = (pokemon) => (event) => {
// update captured pokemons list
// update available pokemons list
};
Обновить CaptedPokemons мы можем просто позвонить в setcapturedpokemons Функция с текущим CaptedPokemons и покемон, чтобы быть захваченным.
setCapturedPokemons([...capturedPokemons, pokemon]);
И обновить Покемоны Список, просто фильтруйте покемонов, которые будут захвачены.
setPokemons(removePokemonFromList(pokemon));
RemovePokemonFromList Это просто простая функция для фильтрации покемонов, удалив захваченных покемонов.
const removePokemonFromList = (removedPokemon) => pokemons.filter((pokemon) => pokemon !== removedPokemon)
Как компонент теперь выглядит сейчас?
import React, { useContext } from 'react';
import { PokemonContext } from './PokemonContext';
export const PokemonsList = () => {
const {
pokemons,
setPokemons,
capturedPokemons,
setCapturedPokemons
} = useContext(PokemonContext);
const removePokemonFromList = (removedPokemon) =>
pokemons.filter(pokemon => pokemon !== removedPokemon);
const capture = (pokemon) => () => {
setCapturedPokemons([...capturedPokemons, pokemon]);
setPokemons(removePokemonFromList(pokemon));
};
return (
Pokemons List
{pokemons.map((pokemon) =>
{pokemon.name}
)}
);
};
export default PokemonsList;
Он будет выглядеть очень похожим на захваченный компонент покемонов. Вместо захватывать это будет Выпуск Функция:
import React, { useContext } from 'react';
import { PokemonContext } from './PokemonContext';
const CapturedPokemons = () => {
const {
pokemons,
setPokemons,
capturedPokemons,
setCapturedPokemons,
} = useContext(PokemonContext);
const releasePokemon = (releasedPokemon) =>
capturedPokemons.filter((pokemon) => pokemon !== releasedPokemon);
const release = (pokemon) => () => {
setCapturedPokemons(releasePokemon(pokemon));
setPokemons([...pokemons, pokemon]);
};
return (
CapturedPokemons
{capturedPokemons.map((pokemon) =>
{pokemon.name}
)}
);
};
export default CapturedPokemons;
Сокращение сложности
Теперь мы используем Уместите Крюк, контекст API, а контекстный провайдер упреждающий текст Отказ И, что более важно, мы можем делиться данными между коробками покемонов.
Другим способом управления состоянием является использование Успеведщик как альтернатива Уместите Отказ
Срок службы редуктора работает так: Успеведщик предоставляет Отправка функция. С этой функцией мы можем отправить Действие внутри компонента. Редуктор получает действие и государство. Это понимает тип действия, обрабатывает данные и возвращает новое состояние. Теперь новое состояние может быть использовано в компоненте.
Как упражнение и иметь лучшее понимание этого крючка, я пытался заменить Уместите с этим.
Уместите был внутри PokemonProvider Отказ Мы можем переопределить начальное состояние для доступных и захваченных покемонов в этой структуре данных:
const defaultState = {
pokemons: [
{ id: 1, name: 'Bulbasaur' },
{ id: 2, name: 'Charmander' },
{ id: 3, name: 'Squirtle' }
],
capturedPokemons: []
};
И пройти это значение для Успеведщик :
const [state, dispatch] = useReducer(pokemonReducer, defaultState);
Успеведщик Получает два параметра: редуктор и исходное состояние. Давайте построим Pokemonredureducer Теперь.
Редуктор получает текущее состояние и действие, которое было отправлено.
const pokemonReducer = (state, action) => // returns the new state based on the action type
Здесь мы получаем тип действия и вернем новое состояние. Действие является объектом. Похоже, это выглядит:
{ type: 'AN_ACTION_TYPE' }
Но также может быть больше:
{
type: 'AN_ACTION_TYPE',
pokemon: {
name: 'Pikachu'
}
}
В этом случае мы передадим покемону объекту действий. Давайте паузом на минуту и подумайте о том, что мы хотим сделать внутри редуктора.
Здесь мы обычно обновляем данные и обрабатываем действия. Действия отправляются, поэтому действия являются поведением. И поведение из нашего приложения – захватывать и выпускать ! Это действия, которые нам нужно для обработки здесь.
Это то, что будет выглядеть наш редуктор:
const pokemonReducer = (state, action) => {
switch (action.type) {
case 'CAPTURE':
// handle capture and return new state
case 'RELEASE':
// handle release and return new state
default:
return state;
}
};
Если наш тип действия – ЗАХВАТЫВАТЬ мы обращаемся с этим одним способом. Если наш тип действия – ВЫПУСКАТЬ мы обрабатываем это другим способом. Если тип действия не соответствует ни одному из этих типов, просто верните текущее состояние.
Когда мы захватываем Pokémon, нам нужно обновить обе спины: удалите покемонов из доступного списка и добавьте его в захваченный список. Это состояние – это то, что нам нужно, чтобы вернуться с редуктора.
const getPokemonsList = (pokemons, capturedPokemon) =>
pokemons.filter(pokemon => pokemon !== capturedPokemon)
const capturePokemon = (pokemon, state) => ({
pokemons: getPokemonsList(state.pokemons, pokemon),
capturedPokemons: [...state.capturedPokemons, pokemon]
});
CapturePokemon Функция просто возвращает обновленные списки. GetPokemonsList Удаляет захваченные покемон из доступного списка.
И мы используем эту новую функцию в редукторе:
const pokemonReducer = (state, action) => {
switch (action.type) {
case 'CAPTURE':
return capturePokemon(action.pokemon, state);
case 'RELEASE':
// handle release and return new state
default:
return state;
}
};
Теперь Выпуск Функция!
const getCapturedPokemons = (capturedPokemons, releasedPokemon) =>
capturedPokemons.filter(pokemon => pokemon !== releasedPokemon)
const releasePokemon = (releasedPokemon, state) => ({
pokemons: [...state.pokemons, releasedPokemon],
capturedPokemons: getCapturedPokemons(state.capturedPokemons, releasedPokemon)
});
GetCapturedPokemons Удалите выпущенную покемону из захваченного списка. ReashPokemon Функция возвращает обновленные списки.
Наш редуктор выглядит так сейчас:
const pokemonReducer = (state, action) => {
switch (action.type) {
case 'CAPTURE':
return capturePokemon(action.pokemon, state);
case 'RELEASE':
return releasePokemon(action.pokemon, state);
default:
return state;
}
};
Только один второстепенный рефактор: типы действий! Это строки, и мы можем извлечь их в постоянную и обеспечить диспетчеру.
export const CAPTURE = 'CAPTURE'; export const RELEASE = 'RELEASE';
И редуктор:
const pokemonReducer = (state, action) => {
switch (action.type) {
case CAPTURE:
return capturePokemon(action.pokemon, state);
case RELEASE:
return releasePokemon(action.pokemon, state);
default:
return state;
}
};
Весь файл редуктора выглядит так:
export const CAPTURE = 'CAPTURE';
export const RELEASE = 'RELEASE';
const getCapturedPokemons = (capturedPokemons, releasedPokemon) =>
capturedPokemons.filter(pokemon => pokemon !== releasedPokemon)
const releasePokemon = (releasedPokemon, state) => ({
pokemons: [...state.pokemons, releasedPokemon],
capturedPokemons: getCapturedPokemons(state.capturedPokemons, releasedPokemon)
});
const getPokemonsList = (pokemons, capturedPokemon) =>
pokemons.filter(pokemon => pokemon !== capturedPokemon)
const capturePokemon = (pokemon, state) => ({
pokemons: getPokemonsList(state.pokemons, pokemon),
capturedPokemons: [...state.capturedPokemons, pokemon]
});
export const pokemonReducer = (state, action) => {
switch (action.type) {
case CAPTURE:
return capturePokemon(action.pokemon, state);
case RELEASE:
return releasePokemon(action.pokemon, state);
default:
return state;
}
};
Когда редуктор теперь реализован, мы можем импортировать его в наш провайдер и использовать его в Успеведщик крюк.
const [state, dispatch] = useReducer(pokemonReducer, defaultState);
Как мы находимся внутри PokemonProvider Мы хотим обеспечить некоторое значение для потребляющих компонентов: действия захвата и выпуска.
Эти функции просто нужно отправлять правильный тип действий и передавать покемону для редуктора.
-
захватФункция: он получает Pokémon и возвращает новую функцию, которая отправляет действие с типомЗАХВАТЫВАТЬи захваченный покемон.
const capture = (pokemon) => () => {
dispatch({ type: CAPTURE, pokemon });
};
-
ВыпускФункция: он получает Pokémon и возвращает новую функцию, которая отправляет действие с типомВЫПУСКАТЬи выпущенный покемон.
const release = (pokemon) => () => {
dispatch({ type: RELEASE, pokemon });
};
Теперь с государством и реализованными действиями мы можем предоставить эти значения потребленным компонентам. Просто обновите Value Provider Prop.
const { pokemons, capturedPokemons } = state;
const providerValue = {
pokemons,
capturedPokemons,
release,
capture
};
{props.children}
Большой! Теперь обратно к компоненту. Давайте будем использовать эти новые действия. Все логики захвата и выпуска инкапсулированы в нашем провайдере и редукторе. Наш компонент теперь довольно чистый. упреждающий текст будет выглядеть так:
const { pokemons, capture } = useContext(PokemonContext);
И весь компонент:
import React, { useContext } from 'react';
import { PokemonContext } from './PokemonContext';
const PokemonsList = () => {
const { pokemons, capture } = useContext(PokemonContext);
return (
Pokemons List
{pokemons.map((pokemon) =>
{pokemon.name}
)}
)
};
export default PokemonsList;
Для захваченного компонента покемонов он будет выглядеть очень похоже на упреждающий текст :
const { capturedPokemons, release } = useContext(PokemonContext);
И весь компонент:
import React, { useContext } from 'react';
import { PokemonContext } from './PokemonContext';
const Pokedex = () => {
const { capturedPokemons, release } = useContext(PokemonContext);
return (
Pokedex
{capturedPokemons.map((pokemon) =>
{pokemon.name}
)}
)
};
export default Pokedex;
Нет логики. Просто интерфейс. Очень чистый.
Покемон Бог – Создатель
Теперь, когда у нас есть связь между двумя списками, я хочу построить третью коробку. Это будет как мы создаем новую покемону. Но это просто простой вход и отправка кнопки.
Когда мы добавляем имя Pokémon на вход и нажмите кнопку, она отправит действие, чтобы добавить этот покемон в доступный список.
Как нам нужно получить доступ к доступным списке для его обновления, нам нужно поделиться состоянием. Так что наш компонент будет обернут нашими PokemonProvider вместе с другими компонентами.
const App = () => ();
Давайте построим Pokemonform компонент сейчас. Форма довольно простая:
У нас есть форма, вход и кнопка. Подводя итог, у нас также есть функция для обработки отправки формы и другой функции для обработки ввода на изменение.
handlenameonchange Будут вызвать каждый раз, когда пользовательские типы или удаляют символ. Я хотел построить местное государство, представление имени покемона. С этим состоянием мы можем использовать его для отправки при отправке формы.
Как мы хотим попробовать крючки, мы будем использовать Уместите обрабатывать это локальное состояние.
const [pokemonName, setPokemonName] = useState(); const handleNameOnChange = (e) => setPokemonName(e.target.value);
Мы используем SetPokemonName обновить Имя покемона Каждый раз, когда пользователь взаимодействует с входом.
И Handleformsubmit Это функция для отправки нового Pokémon, которая будет добавлена в доступный список.
const handleFormSubmit = (e) => {
e.preventDefault();
addPokemon({
id: generateID(),
name: pokemonName
});
};
AddPokemon Является ли API, который мы построим позже. Он получает удостоверение личности покемона и название. Название местное состояние, которое мы определены, Имя покемона Отказ
генерация это просто простая функция, которую я создал для создания случайного числа. Похоже, это выглядит:
export const generateID = () => {
const a = Math
.random()
.toString(36)
.substring(2, 15)
const b = Math
.random()
.toString(36)
.substring(2, 15)
return a + b;
};
AddPokemon будет предоставлен контекстным API, который мы строим. Таким образом, эта функция может получить новый покемон и добавить в доступный список. Похоже, это выглядит:
const addPokemon = (pokemon) => {
dispatch({ type: ADD_POKEMON, pokemon });
};
Это отправляет этот тип действий Add_pokemon а также пройти покемон.
В нашем редукторе мы добавляем корпус для Add_pokemon и обрабатывать состояние, чтобы добавить новый покемон в состояние.
const pokemonReducer = (state, action) => {
switch (action.type) {
case CAPTURE:
return capturePokemon(action.pokemon, state);
case RELEASE:
return releasePokemon(action.pokemon, state);
case ADD_POKEMON:
return addPokemon(action.pokemon, state);
default:
return state;
}
};
И AddPokemon Функция будет:
const addPokemon = (pokemon, state) => ({
pokemons: [...state.pokemons, pokemon],
capturedPokemons: state.capturedPokemons
});
Другой подход – разрушать государство и изменить только атрибут Pokémon, как это:
const addPokemon = (pokemon, state) => ({
...state,
pokemons: [...state.pokemons, pokemon],
});
Вернуться к нашему компоненту, нам просто нужно убедиться, что упреждающий текст предоставляет AddPokemon Отправка API на основе PokemonContext :
const { addPokemon } = useContext(PokemonContext);
И весь компонент выглядит так:
import React, { useContext, useState } from 'react';
import { PokemonContext } from './PokemonContext';
import { generateID } from './utils';
const PokemonForm = () => {
const [pokemonName, setPokemonName] = useState();
const { addPokemon } = useContext(PokemonContext);
const handleNameOnChange = (e) => setPokemonName(e.target.value);
const handleFormSubmit = (e) => {
e.preventDefault();
addPokemon({
id: generateID(),
name: pokemonName
});
};
return (
);
};
export default PokemonForm;
Теперь у нас есть доступный список покемонов, захваченный список покемонов и третье поле для создания новых покемонов.
Эффекты покемонов
Теперь, когда у нас есть наше приложение почти завершено, мы можем заменить список издевателей покемонов со списком покемонов из покеапи.
Таким образом, внутри компонента функций мы не можем выполнять какие-либо побочные эффекты, такие как регистрация или подписки. Вот почему Useffect Крюк существует. С помощью этого крючка мы можем получить Pokémon (побочный эффект) и добавить в список.
Выбирая из покепи выглядит так:
const url = "https://pokeapi.co/api/v2/pokemon";
const response = await fetch(url);
const data = await response.json();
data.results; // [{ name: 'bulbasaur', url: 'https://pokeapi.co/api/v2/pokemon/1/' }, ...]
Результаты Атрибут – это список извлеченных покемонов. С помощью этих данных мы сможем добавить их в список покемонов.
Давайте получим код запроса внутри Useffect :
useEffect(() => {
const fetchPokemons = async () => {
const response = await fetch(url);
const data = await response.json();
data.results; // update the pokemons list with this data
};
fetchPokemons();
}, []);
Чтобы быть в состоянии использовать async-await. Нам нужно создать функцию и позвонить позже. Пустой массив является параметром, чтобы убедиться, что Useffect Знает зависимости, которые он будет смотреть, чтобы повторно запустить.
Поведение по умолчанию – запуск эффекта каждого заполненного рендера. Если мы добавим зависимость в этот список, Useffect будет только повторно запустить при изменении зависимости, а не запуска во всех завершенных рендерах.
Теперь, когда мы получили покемонов, нам нужно обновить список. Это действие, новое поведение. Нам нужно снова использовать отправку, реализовать новый тип в редукторе и обновлять состояние в контексте поставщика.
В PokemonContext мы создали AddPokemons Функция для предоставления API к потребляемому компоненту, используя его.
const addPokemons = (pokemons) => {
dispatch({ type: ADD_POKEMONS, pokemons });
};
Получает Pokémon и Dispatches новое действие: Add_pokemons. .
В редукторе мы добавляем этот новый тип, ожидайте, что Pokémon и вызовите функцию, чтобы добавить Pokémon на доступное состояние списка.
const pokemonReducer = (state, action) => {
switch (action.type) {
case CAPTURE:
return capturePokemon(action.pokemon, state);
case RELEASE:
return releasePokemon(action.pokemon, state);
case ADD_POKEMON:
return addPokemon(action.pokemon, state);
case ADD_POKEMONS:
return addPokemons(action.pokemons, state);
default:
return state;
}
};
AddPokemons Функция просто добавляет Pokémon в список:
const addPokemons = (pokemons, state) => ({
pokemons: pokemons,
capturedPokemons: state.capturedPokemons
});
Мы можем ревертировать это, используя деструктурирующуюся состояние и значение свойства объекта:
const addPokemons = (pokemons, state) => ({
...state,
pokemons,
});
Поскольку мы предоставляем эту функцию API для потребленного компонента сейчас, мы можем использовать упреждающий текст чтобы получить это.
const { addPokemons } = useContext(PokemonContext);
Весь компонент выглядит так:
import React, { useContext, useEffect } from 'react';
import { PokemonContext } from './PokemonContext';
const url = "https://pokeapi.co/api/v2/pokemon";
export const PokemonsList = () => {
const { state, capture, addPokemons } = useContext(PokemonContext);
useEffect(() => {
const fetchPokemons = async () => {
const response = await fetch(url);
const data = await response.json();
addPokemons(data.results);
};
fetchPokemons();
}, [addPokemons]);
return (
Pokemons List
{state.pokemons.map((pokemon) =>
{pokemon.name}
)}
);
};
export default PokemonsList;
Обертывание
Это была моя попытка поделиться тем, что я узнал, пытаясь использовать крючки в мини-боковом проекте.
Мы узнали, как обращаться с местным государством с Уместите Создание глобального состояния с контекстом API, как переписать и заменить Уместите с Успеведщик и как делать побочные эффекты в Useffect Отказ
Отказ от ответственности: Это был просто экспериментальный проект для учебных целей. Возможно, я не использовал лучшие практики для крючков или сделал их масштабируемыми для больших проектов.
Я надеюсь, что это было хорошее чтение! Продолжайте учиться и кодировать!
Вы можете другие статьи такие в моем блоге .
Ресурсы
- React Docs: контекст
- Реагистрировать документы: Крючки
- Pokemon Hooks Side-Project: исходный код
- Узнать реагировать, создавая приложение
Оригинал: “https://www.freecodecamp.org/news/building-a-simple-pokemon-web-app-with-react-hooks-and-context-api/”