React Navigation: как обновить заголовок навигации для родителя, когда значение приходит из redux и обновляется в дочернем?

Я использую react-navigation и имеет StackNavigator с ParentScreen и ChildScreen.

Оба экрана имеют одну и ту же навигационную панель с динамическим значением от redux. Выполнено, как описано в Проблема № 313

Это работает так, как ожидалось. Когда я нахожусь в DetailScreen, и я обновляю значение для переменной count, он также обновляет значение в панели навигации.

Проблема в том, что если я вернусь к родительской сцене, в навигационной панели все еще остается старое значение. Он не обновляется до текущего значения в магазине redux.

Ребенок

screen shot 2017-04-11 at 15 20 28

Родитель (когда я вернусь)

screen shot 2017-04-11 at 15 21 31

ChildScreen

class ChildScreen extends Component {
  static navigationOptions = {
    title: ({ state }) => `Total: ${state.params && state.params.count ?  state.params.count : ''}`
  };

  componentWillReceiveProps(nextProps) {
    if (nextProps.count != this.props.count) {
      this.props.navigation.setParams({ count: nextProps.count });
    }
  }

  render() {
    return (
      <View>
        <Button onPress={() => this.props.increment()} title="Increment" />
      </View>
    );
  }
}

ParentScreen

class ParentScreen extends Component {
  static navigationOptions = {
  title: ({ state }) => `Total: ${state.params && state.params.count ?    state.params.count : ''}`
  };
}

Любые советы?

Ответ 1

Мой совет:

  • Убедитесь, что ParentScreen подключен через функцию response-redux connect.

  • Если вы хотите, чтобы заголовок ParentScreen автоматически обновлялся при изменении состояния хранилища, его подключения недостаточно. Вам нужно будет использовать componentWillReceiveProps, как вы делаете в компоненте ChildScreen.

Бонус: вы можете создать компонент более высокого порядка для инкапсуляции этого поведения, например:

const withTotalTitle = Component => props => {
  class TotalTitle extends Component {
    static navigationOptions = {
      title: ({ state }) => `Total: ${state.params && state.params.count ?  state.params.count : ''}`
    };

    componentWillReceiveProps(nextProps) {
      if (nextProps.count != this.props.count) {
        this.props.navigation.setParams({ count: nextProps.count });
      }
    }

    render() {
      return (
        <Component {...props}/>
      );
    }
  }

  return connect(state => { count: state.total })(TotalTitle); // update this (I have no idea what the structure your state looks like)
};

И тогда вы можете использовать его следующим образом:

const ChildScreen = withTotalTitle(({ increment }) => (
  <View>
    <Button onPress={() => increment()} title="Increment" />
  </View>
));

const ParentScreen = withTotalTitle(() => (
  <View>
    <Text>Whatever ParentScreen is supposed to render.</Text>
  </View>
));

Ответ 2

OP, это, вероятно, будет проблемой с вашей редукцией. Вы знакомы с тем, как redux реализует свой магазин? Я не вижу здесь упоминания, что означает, что, скорее всего, ваша функция increment просто обновляет состояние дочернего компонента вместо отправки действий и редукторов. Пожалуйста, взгляните на правильную реализацию редукции, подобную этой: https://onsen.io/blog/react-state-management-redux-store/

Ответ 3

Имейте общий редуктор как для родителя, так и для ребенка. Таким образом, все компоненты (родительский и дочерний в вашем случае) получат уведомление при изменении состояния.

Напишите функцию подключения как для родителя, так и для ребенка. Вы получите обновленное состояние в методе componentWillReceiveProps. Используйте его, как вам угодно.

Надеюсь, это поможет.

Ответ 4

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

найти статью ниже. Он имеет отличный пример связи между родительскими и дочерними компонентами.

http://andrewhfarmer.com/component-communication/

Спасибо