Магазин Redux обновляет все, даже если я просто обновляю вложенный атрибут?

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

function EditName(props) {
    const { navigation, dispatch, initFirstName } = props;

    const [text, setText] = useState(initFirstName);

    return (
      <>
        <Button title="Save" onPress={() => dispatch(updateFirstName(text))} />
        <TextInput
          style={{ height: 40, borderColor: 'gray', borderWidth: 1 }}
          onChangeText={(inp) => setText(inp)}
          value={text}
        />
      </>

    )


}

function mapStateToProps(state) {
  return (
    {
      initFirstName: state.user.data.firstName,
    }
  );
}

export default connect(mapStateToProps)(EditName);

Но теперь я столкнулся с проблемой, если пользователь нажимает кнопку сохранения и обрабатывается dispatch(updateFirstName(text)). text снова перезаписывается initFirstName.

Мой магазин Redux (toolkit) устроен следующим образом:

{
  data: {
    firstName: "Test"
  },
  updateFirstName: {
   pending: null,
   error: null,
  },    
}

Метод updateFirstName(text) отправляет действие, которое устанавливает state.updateFirstName.pending = true;. Если я это оставлю - все работает.

Итак, я предполагаю, что создается новая ссылка на хранилище (состояние), и React думает: О, я получил новое имя initFirstName (кроме того, оно все еще то же самое, потому что обновление еще не произошло).

Что было бы лучшим способом сделать это? Какое решение этой проблемы?


person RaideR    schedule 24.01.2021    source источник
comment
Как используется ваш EditName Компонент?   -  person Taghi Khavari    schedule 24.01.2021
comment
Это экран в моем родном проекте. Так что это определено в StackNavigator.   -  person RaideR    schedule 24.01.2021
comment
Я предполагаю, что проблема в том, что когда вы обновляете состояние, EditName компоненты получают rerenders, и вам нужно избегать этого.   -  person Taghi Khavari    schedule 24.01.2021
comment
Да - я тоже так думаю. Как бы вы избежали этого или решили этот вариант использования в целом?   -  person RaideR    schedule 24.01.2021
comment
Я думаю, что вы используете EditName неправильным образом, я не могу ответить, если не увижу воспроизводимый пример ваших кодов.   -  person Taghi Khavari    schedule 24.01.2021


Ответы (2)


Возможно, попробуйте создать функцию, которая будет вызываться вместо назначения onPress функции стрелки. По сути, функция будет вызываться с начальным значением text.

Убедитесь, что вы используете текущее значение text, попробуйте следующее:

const saveHandler = () => {
    dispatch(updateFirstName(text))
}
...
<Button title="Save" onPress={saveHandler} />
person Mihai Moraru    schedule 24.01.2021

У @Taghi Khavari было хорошее предположение: это не имело ничего общего с кодом, который я разместил в StackOverflow — это была проблема с React Navigation.

Я использую в своем приложении вложенные навигаторы. Я объявил вложенный навигатор внутри моей функции App, что привело к многократному перемонтированию компонента EditName после изменения состояния (правда, я не знаю, почему).

Когда я объявил вложенные навигаторы ВНЕ моей функции приложения (как в следующем примере), это сработало, и компонент был смонтирован только один раз. Кто-нибудь может объяснить, почему?

function Home() {
  return (
    <NestedStack.Navigator>
      <NestedStack.Screen name="Profile" component={Profile} />
      <NestedStack.Screen name="Settings" component={Settings} />
    </NestedStack.Navigator>
  );
}

function App() {
  return (
    <NavigationContainer>
      <RootStack.Navigator mode="modal">
        <RootStack.Screen
          name="Home"
          component={Home}
          options={{ headerShown: false }}
        />
        <RootStack.Screen name="EditPost" component={EditPost} />
      </RootStack.Navigator>
    </NavigationContainer>
  );
}
person RaideR    schedule 25.01.2021