предупреждение react-native-router-flux: ключ уже определен

Ниже приведен вывод журнала Android, когда приложение React Native запускается на некоторое время, прежде чем отключить его от сервера Meteor (DDP), уничтожив сервер Meteor.

Используя console.log("<App /> render"), чтобы указать, когда вызывается функция render компонента App, кажется, что всякий раз, когда функция render вызывается снова после того, как createContainer передает ей новый props, возникает ошибка Key is already defined.

Что вызывает эту ошибку/предупреждение и как мы можем это исправить? Приложение по-прежнему работает нормально, но здесь определенно что-то не так.

12-23 02:27:01.875 31197 19338 I ReactNativeJS: Running application "RNapp" with appParams: {"initialProps":{},"rootTag"
:1}. __DEV__ === true, development-level warning are ON, performance optimizations are OFF
12-23 02:27:01.891 31197 19338 I ReactNativeJS: render
12-23 02:27:01.995 31197 19338 I ReactNativeJS: Connected to DDP server.
12-23 02:27:01.999 31197 19338 I ReactNativeJS: Connected to DDP server.
12-23 02:27:02.012 31197 19338 I ReactNativeJS: render
12-23 02:27:02.013 31197 19338 I ReactNativeJS: Key home is already defined!
12-23 02:27:02.013 31197 19338 I ReactNativeJS: Key welcome is already defined!
12-23 02:27:02.013 31197 19338 I ReactNativeJS: Key loading is already defined!
12-23 02:27:02.013 31197 19338 I ReactNativeJS: Key root is already defined!
12-23 02:27:34.592 31197 19338 I ReactNativeJS: Disconnected from DDP server.
12-23 02:27:34.593 31197 19338 I ReactNativeJS: Disconnected from DDP server.
12-23 02:27:34.599 31197 19338 I ReactNativeJS: <App /> render
12-23 02:27:34.599 31197 19338 I ReactNativeJS: Key home is already defined!
12-23 02:27:34.599 31197 19338 I ReactNativeJS: Key welcome is already defined!
12-23 02:27:34.599 31197 19338 I ReactNativeJS: Key loading is already defined!
12-23 02:27:34.599 31197 19338 I ReactNativeJS: Key root is already defined!
12-23 02:27:34.609 31197 19338 I ReactNativeJS: <Loading /> render
12-23 02:27:35.603 31197 19338 I ReactNativeJS: Disconnected from DDP server.
12-23 02:27:35.613 31197 19338 I ReactNativeJS: <App /> render
12-23 02:27:35.613 31197 19338 I ReactNativeJS: Key home is already defined!
12-23 02:27:35.613 31197 19338 I ReactNativeJS: Key welcome is already defined!
12-23 02:27:35.613 31197 19338 I ReactNativeJS: Key loading is already defined!
12-23 02:27:35.613 31197 19338 I ReactNativeJS: Key root is already defined!
12-23 02:27:45.599 31197 19338 I ReactNativeJS: Disconnected from DDP server.
12-23 02:27:45.616 31197 19338 I ReactNativeJS: <App /> render
12-23 02:27:45.616 31197 19338 I ReactNativeJS: Key home is already defined!
12-23 02:27:45.616 31197 19338 I ReactNativeJS: Key welcome is already defined!
12-23 02:27:45.616 31197 19338 I ReactNativeJS: Key loading is already defined!
12-23 02:27:45.616 31197 19338 I ReactNativeJS: Key root is already defined!

index.android.js

import { AppRegistry } from 'react-native'

import App from './app/App.js'

AppRegistry.registerComponent('RNapp', () => App)

App Компонент

export class App extends Component {

    constructor(props) {
        super(props);
    }

    componentWillReceiveProps(nextProps) {
        if (nextProps.status.connected == false) {
            Actions.loading();
        } else {
            if (nextProps.user !== null) {
                Actions.home();
            } else {
                Actions.welcome();
            }
        }
    }


    render() {
       console.log('<App /> render')
        return (
            <Router>
                <Scene key="root">
                    <Scene key="home" component={Home} title="Home" hideNavBar={true} />
                    <Scene key="welcome" component={Welcome} title="Welcome" hideNavBar={true} />
                    <Scene key="loading" component={Loading} title="Loading" hideNavBar={true} />
                    <Scene key="profile" component={Profile} title="Home" hideNavBar={true} />
                    <Scene key="history" component={History} title="Home" hideNavBar={true} />
                    <Scene key="search" component={Search} title="Home" hideNavBar={true} />
                </Scene>
            </Router>
        )       
    }

}


export default createContainer(() => {
  return {
    status: Meteor.status(),
    user: Meteor.user(),
    loggingIn: Meteor.loggingIn(),
  };
}, App);

person Nyxynyx    schedule 28.12.2016    source источник


Ответы (2)


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

const scenes = Actions.create(
  <Scene key="root">
    <Scene key="home" component={Home} title="Home" hideNavBar={true} />
    <Scene key="welcome" component={Welcome} title="Welcome" hideNavBar={true} />
    <Scene key="loading" component={Loading} title="Loading" hideNavBar={true} />
    <Scene key="profile" component={Profile} title="Home" hideNavBar={true} />
    <Scene key="history" component={History} title="Home" hideNavBar={true} />
    <Scene key="search" component={Search} title="Home" hideNavBar={true} />
  </Scene>
)

export class App extends Component {

  constructor(props) {
    super(props);
  }

  componentWillReceiveProps(nextProps) {
    if (nextProps.status.connected == false) {
      Actions.loading();
    } else {
      if (nextProps.user !== null) {
        Actions.home();
      } else {
        Actions.welcome();
      }
    }
  }


  render() {
    console.log('<App /> render')
    return (
      <Router scenes={scenes} />
    )
  }

}

См. docs для получения дополнительной информации.

person Christopher Bradshaw    schedule 26.04.2017
comment
Статичные сцены никак не помогают. Если вызывается рендеринг, маршрутизатор повторно визуализируется, что приводит к генерации предупреждающих сообщений и повторному рендерингу исходного компонента в иерархии сцен. - person Mihai Damian; 18.07.2017

По моему опыту, предупреждения не вызывают никаких проблем, но на всякий случай я обычно определяю метод shouldComponentUpdate, который возвращает false, если свойства/состояние не изменились таким образом, что потребовало бы изменения маршрута (обратите внимание, что я использую избыточность и Redux сохраняется, чтобы решить, что является начальной сценой, и поэтому мне нужно подключить компонент к Redux, чтобы получить необходимую информацию через реквизит, но позже, если данные в хранилище изменятся, я могу безопасно заблокировать дополнительные рендеры).

Это просто мой подход, основанный на моем опыте и потребностях. У ребят из router-flux немного более «строгий» подход к этому, что вы можете увидеть в их документы

person martinarroyo    schedule 28.12.2016