Реагировать на данные Native Pass между одноуровневыми представлениями

Я разрабатываю простое приложение для списка дел с использованием React Native, моя проблема заключается в следующем: у меня есть NavigatorIOS в корне моего проекта с компонентом, содержащим ListView в качестве начального маршрута, и кнопкой панели навигации, которая ведет к представление создания задачи.

После создания новой задачи представление всплывает, чтобы отображался ListView. Я пытаюсь добавить свою недавно созданную задачу в этот ListView (его источник данных содержится в состоянии компонента).

Как выполнить такую ​​операцию, что рекомендуется делать? Я бы использовал делегат в чисто нативном приложении, но здесь оба представления обрабатываются экземпляром NavigatorIOS.

index.ios.js

addTask() {
    console.log("Test");
},

render() {
        return (
            <React.NavigatorIOS
                ref="nav"
                style={styles.container}
                tintColor="#ED6063"
                initialRoute={{
                    title: "Tasks",
                    component: TasksList,
                    rightButtonTitle: 'Add',
                    onRightButtonPress: () => {
                        this.refs.nav.navigator.push({
                            title: "New task",
                            component: NewTask,
                            passProps: {
                                onTaskAdded: this.addTask
                            },
                            leftButtonTitle: "Cancel"
                        });
                    }
                }}/>
        );
    }

NewTask.js

taskAdded() {
console.log("Added: " + this.state.title + " - " + this.state.description);
this.props.onTaskAdded({
    title: this.state.title,
    description: this.state.description
});
this.props.navigator.pop();
}

TaskList.js

var dataSource = new ListView.DataSource({
    rowHasChanged: (r1, r2) => r1 !== r2
});
this.state = {
    dataSource: dataSource.cloneWithRows(data)
};

Вы можете найти полный исходный код здесь.


person sweepy_    schedule 14.04.2015    source источник


Ответы (2)


В документации React-Native есть краткий раздел о подходах к общению между компонентами.

Когда вы пытаетесь сделать что-то более сложное, чем отношения родитель->потомок или потомок->родитель, есть несколько вариантов:

  1. Шаблон менеджера. Для истинной связи между родственными элементами‹->родственными элементами (т. е. когда два родственных элемента имеют общего родителя через композицию) вы можете сделать так, чтобы родитель управлял состоянием. Например, у вас может быть виджет <MyConsole>, у которого есть <TextInput> и <ListView>, содержащие прошлые входные данные пользователя, оба являются дочерними элементами виджета <Console>.

  2. Шаблон события (публикация-подписка). Помните, что компоненты — это всего лишь объекты, поэтому вы можете использовать объектно-ориентированные подходы к взаимодействию между компонентами. В документах React отмечается, что:

    Для связи между двумя компонентами, у которых нет отношения родитель-потомок, вы можете настроить собственную глобальную систему событий. Подпишитесь на события в componentDidMount(), отмените подписку в componentWillUnmount() и вызовите setState() при получении события.

    • Here, you can use a simple publish-subscribe library like pubsub.js so that when one component changes it just publishes the change and other related components can listen for the event and update themselves. This can be a very effective approach for smaller apps.
  3. Шаблон потока. Одним из недостатков чистой системы публикации/подписки является то, что становится трудно отслеживать состояние. Например, если у вас есть 2 компонента (например, EditTitle, EditBody), которые могут обновлять какое-то состояние, например, сообщение электронной почты, то чистая система обработки событий в конечном итоге передает разные версии состояния, вокруг которых могут возникать конфликты, потому что нет «единого версия правды». Вот здесь-то и появляется flux-подход React. С Flux компоненты обновляют хранилище данных. который отвечает за обновление и согласование данных (например, EmailDataStore), а затем хранилище уведомляет компоненты об обновленном состоянии.

    • So in your example, the task view would issue an update (e.g. via publish, or direct function invocation) to a TasksDataStore, which might then publish an event like tasks-updated to its subscribers. Both the tasks panel and the results panel would subscribe to the data store.

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

person tohster    schedule 09.10.2015
comment
tks @tohster, вы правы, лучше всего настроить глобальную систему событий, но я новичок в React-Native, я не знаю, как создать глобальную систему событий в React-Native. - person backslash112; 24.12.2015

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

Сохраняйте список задач в локальный файл или Firebase и читайте при создании.

person KChen    schedule 04.10.2015
comment
Итак, вы предлагаете использовать какую-то огромную глобальную переменную/область для передачи данных между представлениями? Звучит как очень плохая архитектура... - person Blackus; 05.10.2015
comment
@Blackus Иначе как получить список задач? Глобальный не является обязательным. - person KChen; 05.10.2015
comment
Именно в этом суть. При разработке нативного кода мы можем использовать протокол или передавать блоки кода для выполнения (например, обратный вызов). Таким образом, список задач является общим только для этих двух представлений, он не находится на большом общем месте с другими вещами. - person Blackus; 05.10.2015
comment
@Blackus Вы можете передать список в следующий вид в качестве опоры. - person KChen; 05.10.2015