Refre sh предыдущий экран после редактирования состояния и возврата - PullRequest
1 голос
/ 07 мая 2020

Хорошо, я знаю, что в Интернете много спекуляций о том, как это должно быть сделано, но я не доволен большинством из них или они устарели :)

Это упрощенное представление моей установки :

// 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",

Надеюсь, некоторые из вас осознают проблему, с которой я столкнулся. Любая помощь приветствуется.

1 Ответ

0 голосов
/ 30 мая 2020

Хорошо, мне удалось выяснить, в чем дело. Я ошибался, полагая, что проблема была в StackNavigator Мой экран B намного сложнее, чем приведенный мной пример, поэтому я добавлю некоторые детали.

// Class B
render() {
    return <B>
        <CustomTextContainer data={state.item}>
            <CustomText data={state.item.prop1} />
            <CustomText data={state.item.prop2} />
        </CustomTextContainer>
    </B>
}

Оба CustomTextContainer и CustomText подключены к магазину, и у них обоих есть функция shouldComponentUpdate. Очевидно, когда контейнер shouldComponentUpdate возвращает false, детская функция shouldComponentUpdate никогда не вызывается.

Это была моя ошибка. Я читал, что когда ребенок подключен к магазину, он должен получать свои реквизиты напрямую, независимо от его родителя. Это не так.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...