У вас уже много состояний.Не думайте о реакционном хуке, как вы привыкли думать, используя классы или функции, подобные предыдущим версиям реагирования.
Совет: если вы не хотите запутаться и работать с состояниями, как предложения, используйтете же самые «метки» для переменной и попытайтесь, если можете, иметь одно состояние
// From this
const [showHomeButton, setShowHomeButton] = useState(false);
const [recipes, setRecipes] = useState([]);
const [loading, setLoading] = useState(true);
const [search, setSearch] = useState('');
// to this - common understanding
const [state, setState] = useState({
showHomeButton: false,
recipes: [],
loading: true,
search: '',
});
(меньше кода, легко поддерживать)
Об избежаниипередача состояния через провайдера контекста, это не вариант, вам нужно .В противном случае, нет никакой причины использовать его.
Что бы я сделал, это было бы сохранить остальную часть вашего кода и немного изменить последние строки кода.Имея что-то вроде этого:
(кстати, ваша fetchRecipe
функция не получает параметр)
import React, { useState, useEffect } from 'react'
const RecipeContext = React.createContext()
const RecipeProvider = (props) => {
const [state, setState] = useState({
showHomeButton: false,
recipes: [],
loading: true,
search: '',
});
const fetchRecipe = async () => {
const recipeData = await fetch(`https://api.myjson.com/bins/t7szj`);
const { recipes } = await recipeData.json();
setState({
...state,
recipes,
loading: false,
});
};
const handleSubmit = async (e) => {
e.preventDefault();
fetchRecipe(`${url}&q=${search}`);
setState({
...state,
loading: true,
showHomeButton: true
});
}
const handleSearchChange = (e) => {
e.persist();
setState({
...state,
search: e.target.value
});
};
// this might not needed
const handleReturnHome = () => {
fetchRecipe()
};
useEffect(() => {
fetchRecipe()
}, []);
return (
<RecipeContext.Provider value={{
store: state,
actions: {
fetchRecipe,
handleSearchChange,
handleSubmit,
}
}}>
{props.children}
</RecipeContext.Provider>
)
}
export default RecipeProvider;
Конечно, это только пример.Вы также можете использовать useReducer
, как кто-то говорит, так что вы можете обращаться с вашим локальным состоянием, как если бы вы использовали приставку.
Теперь у вас есть два варианта в зависимости от того, используете ли вы Statefull или компонент без состояния .
для statefull компонент: получить доступ к контексту (значению) вашего провайдера, используя:
<RecipeContext.Consumer>
{value => (
<SomeComponent />
)}
</RecipeContext.Consumer>
// OR
class SomeComponent extends Component {
render() {
let value = this.context;
}
}
SomeComponent. contextType = RecipeContext;
для Компоненты без состояния :
const SomeComponent = props => {
const value = useContext(RecipeContext);
};
То, что я объяснил, можно найти здесь: https://es.reactjs.org/docs/hooks-reference.html#usecontext. Также в ссылке вы найдете пример использования useReducer
,В этом случае было бы замечательно, вместо того, чтобы передавать все функции, как я, вы можете передать одно действие dispatch
и передать тип как действие, которое вы хотите вызвать, и получить из него новое состояние..
Но вы ДОЛЖНЫ использовать значение из контекста Provider
.