Полный код демо-версии, используемой в этой статье, находится здесь. react-native-complete-demo.
Когда я впервые получил уведомление от компании о разработке React Native APP, я был очень взволнован, потому что предыдущий технологический стек был в основном Vue и Angular, Я написал только несколько демонстраций для React, и я всегда хотел использовать его на практике. проектов, но шансов не было. Однако время разработки, предоставленное компанией, было очень коротким, и от требований к дизайну до представления первой версии на рассмотрение прошел всего один месяц. С учетом предыдущего опыта использования Vue (даже если вы не очень с ним знакомы, вы можете скачать демо-версию официального сайта и модифицировать его для выхода в интернет, а функции и производительность можно итеративно оптимизировать в будущем) и более 90% бизнес-API были откорректированы совместно со студентами, и я подумал, что месяца будет более чем достаточно.
Хотя последнее приложение онлайн (iOS,андроид), но в процессе разработки было много подводных камней.
Во-первых, было сложно найти готовую демонстрацию приложения React Native. Существующие демонстрации либо слишком просты, например, демонстрации, представленные на официальном сайте React Native.AwesomeProject, эта демонстрация предоставляет только самые простые функции и не включает маршрутизацию (компоненты навигации), управление состоянием и т. д. Хотя в руководствах по React Native упоминается, как выбирать компоненты и сторонние библиотеки для сложных приложений, они не дают полных примеров. С другой стороны, существует множествоReact Native APPХотя с открытым исходным кодом, они являются полноценными приложениями для определенных случаев.Структура каталогов некоторых приложений сама по себе неудобна, и нет полной документации.
Во-вторых, кривая обучения React сама по себе относительно крутая, особенно когда дело доходит до управления состоянием, трудно найти код, который можно копировать-вставить напрямую, кроме того, к самому нативному приложению предъявляется множество требований, отличных от веб-приложений. .
По вышеуказанным причинам я решил написать статью с подробным описанием процесса разработки приложения React Native.
Контента много, он разбит на две части, основное содержание этой части:
- Первоначальное использование реагирующей навигации в качестве компонента маршрутизации (навигации)
- пользовательский компонент
- Отправлять сетевые запросы через API выборки
- Интегрируйте избыточность и внедрите постоянное хранилище состояния избыточности.
подготовка
1.1 Инструменты разработки
Если вы хотите разработать приложение для iOS и опубликовать его в APP Store, вы должны использовать Xcode и иметь учетную запись разработчика Apple. Если вы разрабатываете приложения для Android, хорошо иметь компьютер, а лучше всего иметь лестницу.
1.2 Проверка кода и автоматическая коррекция
Прежде чем приступить к изменению кода, рекомендуется установить eslint и prettier в качестве инструментов проверки кода и автоматического форматирования, которые могут гарантировать согласованность написанного вами кода и избежать низкоуровневых ошибок.Я использую vscode в качестве редактора, и я написал статья передVSCode настроить реакцию среды разработки, если вы также используете vscode, вы можете обратиться к нему.
Конечной целью является сохранение кода после операции и автоматическое форматирование кода в соответствии с конфигурацией eslint.
2 Загрузка официальной демоверсии и введение
Официальная демонстрация, хоть и неполная, но хорошее начало. После ознакомления с официальной демонстрацией (включая настройку среды) в следующих разделах будет пошагово показано, как преобразовать эту незавершенную официальную демонстрацию в готовое к использованию приложение.
2.1 Конфигурация среды
Загрузите официальную демоверсию: AwesomeProject и запустите ее.
Требуемая конфигурация средыофициальная документацияЭто очень ясно и не будет повторяться здесь. Следует отметить, что React Native предоставляет два метода запуска Demo: один из нихExpoЗапустите в клиенте, другой — скомпилируйте в собственный код (Android скомпилирован в Java, iOS скомпилирован в Objective-C), а затем запустите в симуляторе или на реальной машине. Рекомендуется использовать второй напрямую.Если вы хотите опубликовать приложение, вы не можете обойти его.
Если вы раньше не разрабатывали нативное ПРИЛОЖЕНИЕ, вам также необходимо ознакомиться с инструментами разработки нативного ПРИЛОЖЕНИЯ: Использование AndroidAndroid Studio, iOS используетXcode. Как они работают с React Nativeофициальная документацияЗаявлено, что ям в этой части не много, а у гугла вообще есть решение при возникновении проблем.
Следует отметить, что для многих обновлений зависимостей Android Studio требуется доступ к службам Google, поэтому принесите свою собственную лестницу.
существуетstep_by_step/other/react/react_native/Подробно описаны проблемы и решения, с которыми я столкнулся в процессе использования React Native впервые.Поскольку это для целей записи, то немного многословно.Если вам интересно, то можете прочитать.
2.2 Введение в официальный демо-каталог
Хорошая структура каталогов полезна для будущей разработки и обслуживания.Для каждой новой функции, добавленной во второй половине этой статьи, в дополнение к кодовой части, если структура каталогов изменится, она будет выделена. Во-первых, давайте взглянем на структуру каталогов официальной демоверсии:
Вышеупомянутая структура каталогов описана следующим образом, важными из них являются:
-
android/
Собственный код Android (используйте студию Android, чтобы открыть этот каталог, если вы откроете родительский каталог напрямую, будет сообщено об ошибке) -
ios/
Собственный код ios (используйте xcode, чтобы открыть этот каталог, если вы откроете родительский каталог напрямую, будет сообщено об ошибке) -
index.js
Введите входной файл React Native (часть js) при упаковке приложения (Android и ios совместно используют входной файл после 0.49) -
App.js
Это можно понимать как входной файл части кода React Native (часть js), например, здесь импортируется маршрутизация всего проекта.
Выше приведены четыре наиболее важных каталога/файла, остальные описания следующие:
-
_test_/
Для тестирования (еще не использовал) -
app.json
Описание проекта, в основном для нативной упаковки приложений, включая название проекта и отображаемое имя мобильного рабочего стола.React Native : 0.41 app.json -
package.json
Файл конфигурации пакета зависимостей проекта -
node_modules
Каталог установки пакета зависимостей -
yarn.lock
файл управления пакетами пряжи - Другие файлы конфигурации пока не нужно изменять, и здесь они не будут объясняться.
3 Настроить маршрутизацию
использовать здесьreact navigationМаршрутизация управления, большое и всестороннее введение или объяснение принципа не является целью этой части, вот как ее использовать.
Существует три распространенных API для интерактивной навигации:
-
StackNavigator
: Переход между страницами (предыдущая страница будет помещаться в стек возврата после каждого перехода, особенно полезно возвращаться на предыдущую страницу) -
TabNavigator
: переход на верхнюю или нижнюю вкладку, обычно используется внизу -
DrawerNavigator
: боковая навигация
Первые два являются наиболее часто используемыми, и только первые два представлены ниже.
3.1 StackNavigator реализует переходы между страницами
Сначала нам нужно настроить структуру каталогов, скорректированная структура выглядит следующим образом:
-
src/
Поместите весь оригинальный реагирующий нативный код -
config/
Файлы конфигурации, такие как конфигурация маршрутизации -
route.js
файл конфигурации маршрутизации -
screens/
все файлы страниц -
ScreenHome/
Этот каталог предназначен для конкретных файлов подкачки. Для дальнейшего разделения кода он разделен на три файла:index.js
содержит логическую часть,style.js
содержит раздел стилей;view.js
Содержит раздел элемента представления или страницы. Остальная часть структуры копии страницы такая же.
Обратите внимание на метод именования файлов подкачки: большой верблюжий регистр, React Native рекомендует именовать компоненты с большим верблюжьим регистром, и каждая страница эквивалентна компоненту.
Краткое введение в реагирующую навигацию и следующие конкретные модификации:
1) Сначала настройте маршрутизацию: файл маршрутизацииroute.js
В настоящее время содержание выглядит следующим образом, что такжеStackNavigator
Самый простой способ использования:
/**
* route.js
*/
// 引入依赖
import React from "react";
import { StackNavigator } from "react-navigation";
// 引入页面组件
import ScreenHome from "../screens/ScreenHome";
import ScreenSome1 from "../screens/ScreenSome1";
// 配置路由
const AppNavigator = StackNavigator({
ScreenHome: {
screen: ScreenHome
},
ScreenSome1: {
screen: ScreenSome1
}
});
export default () => <AppNavigator />;
2) ОбновлениеApp.js
, файл маршрутизации стыковки:
/**
* App.js
*/
export default class RootApp extends Component {
constructor(props) {
super(props);
}
render() {
// 渲染页面
return <Route />;
}
}
3) Конкретные настройки страницы дляScreenHome
Например
существуетindex.js
Настройте логику маршрутизации и стили текущей страницы, такие как заголовок и его стили, настраиваемые кнопки в панели навигации и т. д. Пока нам нужно просто установить заголовок:
/**
* ScreenHome/index.js
*/
export default class ScreenHome extends Component {
// 自定义当前页面路由配置,后面介绍的TabNavigator也使用这个对象中的属性
static navigationOptions = {
// 设置 title
title: "首页"
};
constructor(props) {
super(props);
this.navigation = props.navigation;
}
render() {
return view(this);
}
}
существуетview.js
Определите определенные страницы перехода для определенных элементов в
/**
* ScreenHome/index.js
*/
// 引入依赖略
export default self => (
<View>
<Text style={{ fontSize: 36 }}>home</Text>
<Button
title="goSomePage1"
// 路由跳转
onPress={() => self.navigation.navigate("ScreenSome1")}
/>
</View>
);
После приведенной выше конфигурации эффект выглядит следующим образом:
3.2 TabNavigator реализует переключение вкладок внизу страницы
первый вscreens
новый каталогScreenBottomTab
страница для настройкиTabNavigator
. Каждая вкладка соответствует странице, при необходимости создайте новую страницу, и вновь созданная страница должна быть вroute.js
Обновленная структура каталогов выглядит следующим образом:
-
ScreenBottomTab
Настроить навигацию по нижней вкладке -
ScreenTab1/2/3
Создайте новую страницу с навигацией по нижней вкладке
1) Минимальная конфигурация без значка вкладки
Нужно только настроитьScreenBottomTab
внутриindex.js
Файл в порядке, как показано ниже:
/**
* ScreenBottomTab/index.js
*/
const ScreenTab = TabNavigator(
// 配置 tab 路由
{
ScreenHome: {
screen: ScreenHome
},
ScreenTab1: {
screen: ScreenTab1
},
ScreenTab2: {
screen: ScreenTab2
},
ScreenTab3: {
screen: ScreenTab3
}
},
// 其他配置选项
{
tabBarPosition: "bottom"
}
);
export default ScreenTab;
Файл подкачки теперь настраивать не нужно, следует отметить, что текст под вкладкой по умолчанию, а вStackNavigator
То же, что заголовок навигации заголовка, определенный в .
2) Настройте значок вкладки
В дополнение к настройке значок вкладки также должен отображать разные цвета в зависимости от того, выбран он или нет.Это можно настроить, настроивTabNavigator
изtabBarIconРеализация, конкретный файл, который нужно изменить, - это страница, соответствующая вкладкеindex.js
документ.
/**
* ScreenHome/index.js
*/
static navigationOptions = {
title: '首页',
tabBarIcon: ({ focused }) => {
// 根据是否选中,显示不同图片
const icon = focused
? require('../../assets/images/tab_home_active.png')
: require('../../assets/images/tab_home.png');
return <Image source={icon} style={{ height: 22, width: 22 }} />;
},
};
Окончательный эффект выглядит следующим образом:
3.3 Переключение модального режима на одной странице
Общие требования для ios: страница входа в систему вводится снизу вверх, в то время как другие страницы по умолчанию вводятся слева направо Навигация React предоставляет только способ глобальной настройки страницы и не дает возможности взаимодействовать одна страница, но эту функцию еще можно реализовать, это во второй частиРазработка React Native APP — начиная с преобразования официальной демоверсии (2)введено в.
Четыре пользовательских компонента
React Native инкапсулировал много общих компонентов, но иногда нам все еще нужно инкапсулировать его на вторичной основе, например, некоторые компоненты требуют многократного повторного использования, а стиль нативного компонента или логика взаимодействия не соответствуют требованиям.
Здесь представлена только настройка структуры каталогов. Конкретный код см. в коде проекта на Github. Поскольку требования к пользовательским компонентам сильно различаются, существует также множество руководств для конкретного процесса написания. Мы не будем их представлять. здесь, но добавляйте только пользовательские компоненты Toast. Структура каталогов настроена следующим образом:
-
components/
Здесь размещаются пользовательские компоненты -
XgToast.js
Специальный код пользовательского компонента
документ
config/pxToDp.js
для адаптации размера, вXgToast.js
в использовании,Разработка React Native APP — начиная с преобразования официальной демоверсии (2)подробно описано.
Пять сетевых запросов
Самым большим преимуществом использования React Native является то, что вам не нужно учитывать совместимость нового синтаксиса.В этом случае естественно использовать более разработанный API.Что касается сетевых запросов, этот проект используетfetch API.
После добавления сетевых запросов структура каталогов настраивается следующим образом:
-
xgHttp.js
настроить API выборки -
xgRequest.js
список API-запросов
5.1 Настройка API выборки
xgHttp.js
Весь код выглядит следующим образом, в нем есть простые комментарии, которые здесь подробно объясняться не будут, можно обратиться к использованию fetch apiВведение в API выборки
/**
* xgHttp.js
*/
// 请求服务器host
const host = "http://api.juheapi.com";
export default async function(
method,
url,
{ bodyParams = {}, urlParams = {} }
) {
const headers = new Headers();
headers.append("Content-Type", "application/json");
// 将url参数写入URL
let urlParStr = "";
const urlParArr = Object.keys(urlParams);
if (urlParArr.length) {
Object.keys(urlParams).forEach(element => {
urlParStr += `${element}=${urlParams[element]}&`;
});
urlParStr = `?${urlParStr}`.slice(0, -1);
}
const res = await fetch(
new Request(`${host}${url}${urlParStr}`, {
method,
headers,
// 如果是 get 或者 head 方法,不添加请求头部
body: method === ("GET" || "HEAD") ? null : JSON.stringify(bodyParams)
})
);
if (res.status < 200 || res.status > 299) {
console.log(`出错啦:${res.status}`);
} else {
return res.json();
}
}
Приведенная выше конфигурация не идеальна. Например, многие интерфейсы в производственной среде имеют функции аутентификации, обычно токен + идентификатор пользователя. В приведенной выше конфигурации этой функции нет. Но теперь реализация этой функции также будет включать в себя место для хранения токена, и после его расширения будет много контента.Отсутствие функции проверки пока не влияет на целостность приложения, поэтому эта яма будет заполнен позже.
5.2 Написание и использование API запроса
- файл со списком API
Я помещаю конкретный код запроса APIxgRequest.js
файл, сget
Запрос, например,xgRequest.js
код показывает, как показано ниже:
/**
* xgRequest.js
*/
import XgHttp from "./xgHttp";
export default {
todayOnHistory: urlPar => XgHttp("GET", "/japi/toh", { urlParams: urlPar })
};
в"/japi/toh"
Для адреса интерфейса здесь я использую агрегированные данныесегодня в историиAPI.
Вызов сводных данныхсегодня в историиЯ использую свой собственный APPKEY, когда я использую API, который вызывается 100 раз в день бесплатно, и после его превышения возвращается ошибка.
request exceeds the limit!
, если вы хотите выполнить больше тестов, просто замените его на свой APPKEY после регистрации.
- использовать
Сначала вызовите интерфейс, чтобы получить данные.
Вызов интерфейса находится в файле подкачкиindex.js
осуществляется вScreenTab1/index.js
Например:
/**
* ScreenTab1/index.js
*/
const urlPar = {
// 大佬们,这个是我申请的聚合数据应用的key,每天只有100免费请求次数
key: '7606e878163d494b376802115f30dd4e',
v: '1.0',
month: Number(this.state.inputMonthText),
day: Number(this.state.inputDayText),
};
// 拿到返回数据后就可以进一步操作了
const todayOnHistoryInfo = await XgRequest.todayOnHistory(urlPar);
Затем отобразите данные.
После получения данных вы можете выполнять дальнейшие операции, которые обычно отображаются на странице.react — это фреймворк, управляемый данными., для динамически изменяющихся отображаемых данных обычно помещаются в React Nativestate
в объекте,state
После изменения он сработаетrender()
Функция повторно отображает измененную часть DOM.
первый вindex.js
Запишите данные, которые должны быть динамически отображены в первую очередьstate
:
/**
* ScreenTab1/index.js
*/
// 将需要动态更新的数据放入 state
this.state = {
todayOnHistoryInfo: {}
};
затем вview.js
читать вstate
данные в:
/**
* ScreenTab1/view.js
*/
{
/* 查询 */
}
<Button title="查询" onPress={() => self.getTodayOnHistoryInfo()} />;
{
/* 展示查询数据 */
}
<Text>
发生了啥事:{self.state.todayOnHistoryInfo.result
? self.state.todayOnHistoryInfo.result[0].des
: "暂无数据"}
</Text>;
вышесказанноеview.js
Код в основном делает две вещи: отправляет команду вызова и отображает возвращенные данные.
Окончательные рендеры выглядят следующим образом:
Шесть встроенных редукторов
В приложении есть некоторые глобальные состояния, общие для всех страниц, такие как состояние входа в систему или баланс учетной записи (все страницы, отображающие баланс после покупки продукта, должны быть обновлены соответствующим образом). В этом проекте используйтеReduxОсуществлять управление состоянием.
После введения redux структура каталогов настраивается следующим образом:
-
redux
Хранить файлы конфигурации, связанные с избыточностью -
actions.js
redux action -
reducers.js
redux reducer -
store.js
redux store
Если у вас нет понятия о редуксе, вы можете прочитать эту статьюНачало работы с Redux
ReduxЭто на самом деле очень сложно использовать, если вы использовали его раньшеvuex, в процессе использования Redux вы обнаружите, что слишком много вещей, которые нужно настраивать самостоятельно (здесь нет ни хорошего, ни плохого, вы не хотите начинать войну, это просто ваш собственный опыт), чтобы упростить работу с Redux, автор Redux разработалreact-redux, хотя он и не сравним с vuex с точки зрения простоты использования, его все же гораздо проще использовать, чем напрямую использовать Redux.
Прежде чем интегрировать Redux для управления состоянием, давайте подумаем над вопросом: какие трудности возникают в процессе интеграции?
Поскольку Redux имеет только один магазин в приложении, этот магазин должен быть общим для всех компонентов (страницы), поэтому сложность интеграции заключается в том, чтоКак сделать этот уникальный магазин доступным для всех компонентов (страницы) и запускать действия. С этой целью в редукс-реакции введеныconnect
функция иProvide
Компоненты, они должны использоваться вместе для достижения избыточной интеграции.
сквозь этоconnect
иProvide
Идея реализации хранилища между компонентами такова:
- Магазин Redux может (обратите внимание, что «можно», а не «должен», необходимо настроить, см. пункт 2)
connect
Метод виден, поэтому в компоненте его можно вызвать вызовомconnect
Метод реализует доступ к хранилищу данных; - Реализовать пару магазинов Redux
connect
Видимое предварительное условие состоит в том, чтоНеобходимо убедиться, что этот компонентProvide
подкомпонент компонента, так что, передав магазин какProvide
Реквизиты компонента могут передаваться всем дочерним компонентам слой за слоем; - но дочерний компонент должен пройти
connect
Метод реализует доступ к хранилищу и не может быть доступен напрямую.
6.1 Знакомство с зависимостями
Во-первых, установить и зависеть от редукции, реагировать-редукс:
yarn add redux react-redux
6.2 Настройка избыточности
Вот конфигурацияactions
, reducers
иstore
.
Говорят, что приложение большое, и лучше всего разделить редукс, но проект пока маленький, и разделения пока нет.
- настроить
actions
/**
* actions.js
*/
export function setUserInfo(userInfo) {
return {
// action 类型
type: "SET_USER_INFO",
// userinfo 是传进来的参数
userInfo
};
}
export function clearReduxStore() {
return {
type: "CLEAR_REDUX_STORE"
};
}
- настроить
reducers
/**
* reducers.js
*/
import { initialState } from "./store";
function reducer(state = initialState, action) {
switch (action.type) {
case "SET_USER_INFO":
// 合并 userInfo 对象
action.userInfo = Object.assign({}, state.userInfo, action.userInfo);
// 更新状态
return Object.assign({}, state, { userInfo: action.userInfo });
case "CLEAR_REDUX_STORE":
// 清空 store 中的 userInfo 信息
return { userInfo: {} };
default:
return state;
}
}
export default reducer;
УведомлениеSET_USER_INFO
Код по этому пути используетObject.assign()
. Это потому чтоreducer
Функция каждый раз возвращает новыйstate
объект,Это означает, что еслиstate
объект содержит несколько свойствreducer
Функция возвращает без слияния предыдущегоstate
, может привести кstate
Свойство объекта отсутствует.
Это очень распространенная ошибка, потому что обычно мы запускаемactions
нужно пройти только в той части, которая измениласьstate
свойства, а не весьstate
Отправьте еще раз.
Учебное пособие по классическому счетчику Redux запускается
state
Обычно так пишут при сменеreturn { defaultNum: state.defaultNum - 1 };
, потому что в контрпримере есть только одно свойство, а именноdefaultNum
, поэтому перед слияниемstate
Это не имеет смысла, но приложение в производственной средеstate
Часто в объекте присутствует более одного атрибута, и описанный выше способ записи будет неправильным.
- настроить
store
/**
* store.js
*/
import { createStore } from "redux";
import reducers from "./reducers";
// 定义初始值
const initialState = {
userInfo: {
name: "小光",
gender: "男"
}
};
const store = createStore(reducers, initialState);
export default store;
6.3 Используемые компоненты
После настройки redux следующим шагом будет его использование.
- настроить
index.js
в конфигурацииindex.js
Среда в основном конфигурацияProvide
как корневой компонент и передатьstore
В качестве его свойства создайте условия для использования избыточности следующим компонентом.
/**
* index.js
*/
import React from "react";
import { AppRegistry } from "react-native";
import { Provider } from "react-redux";
import App from "./App";
import store from "./src/redux/store";
const ReduxApp = () => (
// 配置 Provider 为根组件,同时传入 store 作为其属性
<Provider store={store}>
<App />
</Provider>
);
AppRegistry.registerComponent("AwesomeProject", () => ReduxApp);
- Настроить компоненты
здесь сScreenTab2
Например:
Первый вindex.js
Связано с редукцией в
/**
* ScreenTab2/index.js
*/
// redux 依赖
import { connect } from "react-redux";
import { bindActionCreators } from "redux";
import * as actionCreators from "../../redux/actions";
changeReduxStore(userInfo) {
// 设置 redux store,相当于 dispatch,这里触发 actions 中的 'SET_USER_INFO'
this.props.setUserInfo(userInfo);
}
// 将 store 中的状态映射(map)到当前组件的 props 中,这样才能在该组建中访问 redux state
function mapStateToProps(state) {
return { userInfo: state.userInfo };
}
// 将 actions 中定义的方法映射到当前组件的 props 中,这样才能在该组建中触发 action
function mapDispatchToProps(dispatch) {
return bindActionCreators(actionCreators, dispatch);
}
// 将 store 和 当前组件连接(connect)起来
export default connect(mapStateToProps, mapDispatchToProps)(ScreenTab2);
Затем необходимо контролировать конкретные измененные данные в представлении.
/**
* ScreenTab2/view.js
*/
<Button title="改变名字" onPress={() => self.changeReduxStore({ name: 'vince' })} />
<Button title="改变性别" onPress={() => self.changeReduxStore({ gender: '女' })} />
<Button title="还原" onPress={() => self.changeReduxStore({ name: '小光', gender: '男' })} />
Окончательный рендеринг выглядит следующим образом:
6.4 Постоянное хранилище
К мобильным приложениям обычно предъявляются следующие требования:Если пользователь активно не завершит работу, даже если процесс приложения будет завершен, информация для входа в систему все равно будет сохранена после повторного открытия приложения..
В этом проекте, чтобы облегчить обмен статусом входа между компонентами, я прописал статус входа в хранилище редуксов, но у нативного редукса есть особенность: после обновления страницы хранилище редуктов вернется в исходное состояние. Чтобы выполнить вышеуказанные требования, необходимо рассмотреть решение для постоянного хранилища с избыточным хранилищем. используется в этом проектеredux-persist, ниже описано, как настроить:
- импортировать зависимости
yarn add redux-persist
- Изменить конфигурацию редукса
1) Изменитьstore.js
.
Помимо введенияredux-persist
Кроме того, вот использование реакции роднойAsyncStorageКонтейнер для постоянного хранения. Кроме того, инициализируйтеstate
переехал вreducers.js
середина.
/**
* store.js
* 更改为持久化存储
*/
import { createStore } from "redux";
// 引入 AsyncStorage 作为存储容器
import { AsyncStorage } from "react-native";
// 引入 redux-persist
import { persistStore, persistCombineReducers } from "redux-persist";
import reducers from "./reducers";
// 持久化存储配置
const config = {
key: "root",
storage: AsyncStorage
};
const persistReducers = persistCombineReducers(config, {
reducers
});
const configureStore = () => {
const store = createStore(persistReducers);
const persistor = persistStore(store);
return { persistor, store };
};
export default configureStore;
2) Изменитьreducers.js
просто инициализируйstate
Въезжать. А зачем инициализироватьstate
отstore.js
въезжатьreducers.js
Это действительно беспомощно: иначеstore.js
создан вstore
Если вы сообщите об ошибке, вы заполните яму позже и временно поставите ее наreducers.js
середина.
/**
* reducers.js
* 更改为持久化存储
*/
// 初始化 state 放在这里
const initialState = {
userInfo: {
name: "小光",
gender: "男"
}
};
function reducers(state = initialState, action) {
// ... 代码未修改
}
export default reducers;
- Изменить файлы с помощью редукса
1) Изменить корневой каталогindex.js
:
/**
* index.js
* 更改为持久化存储
*/
import { PersistGate } from "redux-persist/es/integration/react";
import configureStore from "./src/redux/store";
const { persistor, store } = configureStore();
const ReduxApp = () => (
// 配置 Provider 为根组件,同时传入 store 作为其属性
<Provider store={store}>
{/* redux 持久化存储 */}
<PersistGate persistor={persistor}>
<App />
</PersistGate>
</Provider>
);
2) Из-за процесса модификации в постоянное хранилище инициализированныйstate
существуютreducers.js
, поэтому в сопоставлении компонентов страницыstate
Когда вы дойдете до текущей страницы, вам нужно изменить адрес импорта соответствующего атрибута, по-прежнему используйтеScreenTab2
Например:
/**
* ScreenTab2/index.js
* 更改为持久化存储
*/
// 修改前
function mapStateToProps(state) {
// 引用 state.userInfo
return { userInfo: state.userInfo };
}
// 修改后
function mapStateToProps(state) {
// 引用 state.reducers.userInfo
return { userInfo: state.reducers.userInfo };
}
После вышеуказанной модификации может быть реализовано постоянное хранилище избыточности: имя инициализации小光
, изменить наvince
После перезагрузки страницы имя по-прежнемуvince
(а не исходное состояние小光
). Схема эффекта выглядит следующим образом:
Семь Резюме
После этой части введения основная конструкция каркаса приложения завершена.Вторая частьВ основном обсуждается пользовательский интерфейс/взаимодействие, подготовка к выпуску приложения и способы его выпуска, в том числе:
- Исходя из использования реактивной навигации,iOS реализует анимацию входа одной страницы снизу вверх (модально)
- адаптивный размер
- Установите начальную страницу, измените значок на рабочем столе, отображаемое имя приложения, идентификатор приложения
- Релиз пакета
использованная литература
Введение в API выборки
Начало работы с Redux
Понимание метода подключения в React-redux