Хорошо, я знаю, что в Интернете много спекуляций о том, как это должно быть сделано, но я не доволен большинством из них или они устарели :)
Это упрощенное представление моей установки :
// Navigator
const Stack = createStackNavigator();
<Stack.Navigator
initialRouteName={"A"}
>
<Stack.Screen
name={"A"}
component={A}
/>
<Stack.Screen
name={"B"}
component={B}
/>
<Stack.Screen
name={"C"}
component={C}
/>
</Stack.Navigator>
Redux - это мой предпочтительный менеджер состояний, и он отлично работает с моими 3 фиктивными экранами. Вот фиктивное состояние и редуктор:
const initialState = {
items: [
{prop: "a"},
{prop: "b"},
{prop: "c"},
]
}
const dummyReducer = (state = initialState, action) => {
switch(action.type) {
case "EDIT":
const dummyEdit = state.items.pop();
dummyEdit.prop = "c (edited)";
return {
items = [...state.items, dummyEdit]
}
}
}
А вот и мои очень инновационные экраны
// Class A
render() {
return <A>
<ListView ... data={state.items} />
</A>
}
// Class B
render() {
return <B>
<Text>state.item.prop</Text>
</B>
}
// Class C
render() {
return <C>
<Input value={state.item.prop}
onChangeText={text => dispatch({type: EDIT})}
></Input>
</C>
}
Итак, screen A
- это просто список, который переходит на экран B
, который отображает свойства элемента. На экране B
вы можете редактировать этот элемент, после чего вы перейдете на экран C
. Когда вы редактируете элемент на экране C
, редуктор обновляет состояние. После этого вы navigation.goBack()
на экран B
.
Все экраны связаны с одним и тем же редуктором и состоянием. Когда я помещаю точку останова в функцию рендеринга экрана B
, я вижу, что состояние действительно обновляется сразу после ввода C
onTextChanged
Что я (думаю, я) знать
- На экране B это не помогает:
shouldComponentUpdate() {return true;}
- Redux лениво сравнивает объект, поэтому
prevState.items === state.items
истинно, и экран не обновляется - Несмотря на то, что вызывается функция
render
, это не означает, что экран будет обновлен - Я могу
navigation.dispatch(StackActions.pop(2)); navigation.navigate("B");
обновить экран B
, но это кажется надуманным и он оставляет вам анимацию обратного перехода
Пакеты
"react": "16.9.0",
"react-native": "^0.61.5",
"react-navigation": "^4.2.2",
"@react-navigation/drawer": "^5.1.1",
"@react-navigation/native": "^5.0.9",
"@react-navigation/stack": "^5.1.1",
Надеюсь, некоторые из вас осознают проблему, с которой я столкнулся. Любая помощь приветствуется.