Я запрыгнул на повод React Hooks и решил собрать вместе приложение React Native, чтобы попытаться дать полную реализацию редукционного / глобального состояния. Я читал несколько статей о том, как это сделать, но у меня есть несколько вопросов.
Я понимаю понятия useState
и useReducer
, но я зацикливаюсь на Context
стороне вещей.
Первый вопрос: Каков наилучший способ передать объект состояния по дереву без использования реквизита? Вот что я имею до сих пор. Обычно без Навигации у вас будет дочерний компонент DispatchContext
, который будет получать реквизит. Но так как у меня есть Навигация, я не хочу передавать состояние вниз по дереву. Я чувствую, что побеждает цель контекста и ловит в целом Я видел некоторые вещи, где value={dispatch}
равно value={{somePieceOfState}}
. Как передать состояние и диспетчеризацию в дерево компонентов?
import React, { useReducer } from 'react';
import Navigation from './Navigation';
import { DispatchContext } from './Context';
import { countReducer } from './reducers';
const App = () => {
const [count, dispatchCount] = useReducer(countReducer, 0);
const dispatch = action => [dispatchCount].forEach(fn => fn(action)); //provides one dispatch for the entire component tree
const state = {
count,
//other pieces of state go here
}
return (
<DispatchContext.Provider value={dispatch}>
<Navigation />
// <ChildComponent someStateProp={count} /> normal way to pass down props
</DispatchContext.Provider>
);
};
export default App;
Второй вопрос: Как лучше всего выполнять действия и создателей действий? Вероятно, на этот вопрос можно ответить в связи с первым вопросом. Вот компонент, прикрепленный к моей навигации.
import React, { useContext } from 'react';
import { View, Text, TouchableOpacity } from 'react-native';
import { DispatchContext } from './Context';
import { countUp, countDown } from './actions';
const Comp1 = () => {
const dispatch = useContext(DispatchContext);
return (
<View>
<TouchableOpacity
onPress={() => dispatch(countUp)}
>
<Text>Up</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={() => dispatch(countDown)}
>
<Text>Down</Text>
</TouchableOpacity>
</View>
);
};
export default Comp1;
Действия, связанные с ним:
import {
COUNT_UP,
COUNT_DOWN
} from './types';
export const countUp = () => {
return {
type: COUNT_UP
};
};
export const countDown = () => {
return {
type: COUNT_DOWN
};
};
и редуктор:
import {
COUNT_UP,
COUNT_DOWN
} from '../actions/types';
export const countReducer = (state, action) => {
console.log(action);
switch (action) {
case COUNT_UP:
return state + 1;
case COUNT_DOWN:
return state - 1;
default:
return state;
}
};
Я знаю действия и диспетчеризацию, и все, что работает, потому что я console.log()
в моем редукторе и получаю ответ. Но когда я console.log(action)
, это показывает, что это функция, само действие вместо типа. Если я console.log(action.type)
, это не определено. Что я здесь не так делаю?
Последний вопрос: Является ли это разумным подходом для комплексного управления состоянием? Я знаю о useEffect()
и подобных вещах, но от любого, кто имел некоторый опыт работы с перехватчиками, это хорошо для вызовов API и отслеживание местоположения и тому подобное? Это расширяемый подход? По сути, я спрашиваю о том, что я не хочу углубляться в это и вынужден реорганизовывать все в компоненты на основе классов, потому что я не могу сделать что-то с крючками, которые мне нужны с классами. Но мне действительно нравится эта вещь с крючками, и я хочу придерживаться этого Это хорошо, чтобы двигаться вперед с этим?
Извините за длинный пост, но я чувствую, что эти вопросы, на которые есть ответы, были бы полезны для других, которые хотят попасть в ловушку с реакцией на родной язык.