Перезагрузить приложение React Native из вызова функции в приложении

Я использую AsyncStorage для хранения информации об университете в приложении React Native. Я использую навигаторы стека и вкладок с экранами для своих страниц. Все содержимое страницы успешно перерисовывается так, как я хочу, когда кто-то выбирает другой университет. В заголовке нет. У меня нет способа сообщить ему, что переменная AsyncStorage была обновлена, а также обновить состояние и повторно отобразить себя.

Я хотел бы просто обновить все приложение, как только кто-то выберет новый университет. Тогда переменная, состояния и реквизиты будут обновлены, т. е. то же самое, что вызвать меню Dev и перезагрузить приложение. Мне нужна кнопка в приложении, которая вызывает функцию и делает это внутри.

РЕДАКТИРОВАТЬ: Вот фрагмент кода с моей страницы настроек. Мне нужно, чтобы поле «имя» моей переменной AsyncStorage изменялось в моем заголовке моего индексного файла при нажатии кнопки «Отправить».

saveMSU() {
const object = {
  name: 'MONTANA STATE UNIVERSITY',
  site: 'http://msubobcats.com/index.aspx',
};
AsyncStorage.setItem('schoolObj', JSON.stringify(object));
  }
  saveUM() {
const object = {
  name: 'UNIVERSITY OF MONTANA',
  site: 'http://gogriz.com/',
};
AsyncStorage.setItem('schoolObj', JSON.stringify(object));
  }
  updateSchool = async () => {
this.props.navigation.dispatch(NavigationActions.reset({
  index: 0,
  key: null,
  actions: [NavigationActions.navigate({ routeName: 'Tabs' })]
}));
  }
 render() {
return (
  <View style={styles.container}>
    <Text>CHOOSE YOUR UNIVERSITY</Text>
    <TouchableOpacity onPress={this.saveMSU}>
      <Text>Montana State University</Text>
    </TouchableOpacity>
    <TouchableOpacity onPress={this.saveUM}>
      <Text>University of Montana</Text>
    </TouchableOpacity>
    <Button onPress={this.updateSchool}>
      SUBMIT
    </Button>
  </View>
);
  }
}

Это основная часть моего индексного файла. Когда в настройках нажимается «Отправить», мне нужно обновить this.state.school.site и this.state.school.name. Мне нравится идея использования deviceEventEmitter, но я немного не понимаю, как это реализовать.

class App extends Component {
  state = { school: Object, loaded: false };
  componentWillMount() {
this.retrieveItem('schoolObj').then((current) => {
  this.setState({ school: current, loaded: true });
}).catch((error) => {
  console.log('Unable to retrieve data: ' + error);
});
  }
  async retrieveItem(key) {
try {
  const schoolItem = await AsyncStorage.getItem(key);
  const item = JSON.parse(schoolItem);
  return item;
} catch (error) {
  console.log(error.message);
}
return;
  }
  render() {
return (
  <View style={{ flex: 1 }}>
    <Image style={styles.logoStyle} source={require('./media/UAT.png')} />
    { this.state.loaded &&
      <TouchableOpacity onPress={() => Linking.openURL(this.state.school.site)}>
        <Text style={styles.headingStyle}>
            {Object.values(this.state.school.name)}
        </Text>
      </TouchableOpacity>
    }
    <Root screenProps={this.state.school} />
  </View>
);
  }
 }

person Kincade Pavich    schedule 29.03.2018    source источник
comment
Что насчет этого?? facebook.github.io/react-native/docs/refreshcontrol.html   -  person Rajendran Nadar    schedule 30.03.2018


Ответы (2)


Использование AsyncStorage - действительно плохая идея, поскольку она создает проблему, когда ваш код становится больше, но вы можете справиться с этим, используя setTimeout для AsyncStorage.

AsyncStorage.setItem('title', JSON.stringify(responseJson.data.title));
                                _this.setState({getTitle: true});
                            }, 3000)

В приведенном выше примере показано, как использовать тайм-аут для asyncStore, если вы хотите обновить значение только на той же странице.

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

DeviceEventEmitter.emit('changeTitle', responseJson, null);

Поместите приведенную выше строку кода туда, где вы хотите обновить AsyncStorage. Теперь, чтобы получить это на другой странице или, скажем, в любом месте проекта, просто поместите ниже код в componentDidMount:

componentDidMount() {
        this.emitter = DeviceEventEmitter.addListener('changeToolBarTitle', this.changeToolBarTitle, null);
    }

Не забудьте импортировать DeviceEventEmitter в оба этих файла.

import {
    DeviceEventEmitter
} from 'react-native';

Надеюсь, вы получите свое решение.

person jatin.7744    schedule 30.03.2018
comment
Документации по DeviceEventEmitter очень мало, но это похоже на быстрое решение. Итак, если у меня есть прослушиватель в ComponentDidMount, скажем, в моем индексном файле (где определяется мой текст заголовка), где я могу изменить состояние в зависимости от того, когда этот прослушиватель выполняется? И .emit будет вызываться на моем экране настроек, где обновляется значение AsyncStorage. У меня есть строка в настройках, когда вызывается функция, которая обновляет переменную: AsyncStorage.setItem('schoolObj', JSON.stringify(object)); Затем мне нужно передать это обратно в индекс и обновить заголовок на лету. - person Kincade Pavich; 02.04.2018
comment
Теперь у вашего asyncStorage обновленное значение, верно? поэтому вам нужно использовать это значение asyncStorage там, где вам нужно. - person jatin.7744; 04.04.2018

Немного неясно, почему вы хотите перезагрузить все приложение только для того, чтобы получить доступ к соответствующим данным с другого экрана. Возможно, было бы полезно опубликовать упрощенную версию вашего кода, чтобы ваши намерения были немного ясны.

Я предполагаю, что это связано с тем, что у вас нет контейнера состояния для управления состоянием вашего приложения?

Итак, вот несколько вещей, которые можно попробовать

Redux будет управлять состоянием приложения. Так что вы можете в основном «установить состояние» с любого экрана и получить доступ к этому состоянию с любого экрана (упрощение, но в основном это то, что он делает)

В основном то же самое, что и Redux, но без большого количества шаблонов. Это было бы хорошей отправной точкой перед переходом в Redux. Посмотрите видео об использовании React Context API, чтобы узнать, как его использовать.

Наконец, вам не нужно (не следует) «обновлять все приложение, как только кто-то выберет новый университет». Это было бы излишним и крайне неоптимизированным (не говоря уже о ненужном) способом делать что-то. Кроме того, по мере того, как ваше приложение становится еще немного больше (нетривиальным), этот подход вообще не будет масштабироваться.

Сначала начните с Context (меньше времени на обучение), а если вы хотите пойти дальше, попробуйте Redux (крутая кривая обучения) секунда

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

person hdsenevi    schedule 30.03.2018
comment
Вы правы в том, что полное обновление было бы излишним и неоптимизированным. Это кажется самым простым обходным решением, если бы была одна быстрая строка кода, которая выполняла бы обновление. Кажется, Redux — широко распространенное решение; Мне просто нужно потратить время, чтобы научиться этому. Что касается контекста, я не слышал об этом, и это кажется полезным инструментом. Привязать его к изменениям в переменной AsyncStorage кажется несколько сложным, но это тоже может быть правильным путем. Спасибо за ваш отзыв; это очень полезно. - person Kincade Pavich; 02.04.2018