Что такое ReasonML
ReasonML (или Reason как сокращение от SEO) - это проект с открытым исходным кодом от Facebook, который упрощает использование OCaml для разработчиков JS. Он делает это, предлагая более удобный синтаксис для языка и предоставляя инструменты, которые делают взаимодействие с экосистемой JS таким же гладким, как масло.
OCaml имеет удивительно мощную систему типов, которая заменяет все, что может предложить Flow или TypeScript, а ReasonML поставляется в комплекте с инструментами, которые могут заменить почти все инструменты, которые вы используете, чтобы сделать JS переносимым для ежедневного написания (ESlint → ReasonML / OCaml type system , Flow / TS → синтаксис ReasonML, Prettier → refmt, сборщики модулей JS / ES → модули ReasonML / OCaml, Babel → BuckleScript и т. Д.).
Самое замечательное в ReasonML, поддерживаемом Facebook, заключается в том, что он имеет первоклассную поддержку проектов React через ReasonReact, поэтому, если вы устали бороться с ошибками Flow и все еще не знаете, как TypeScript вписывается в экосистему React, вы должны дать ReasonML попробуйте!
Это руководство призвано помочь вам интегрировать сохранение состояния в ваши приложения ReasonML React Native и способствовать созданию хороших автономных условий для тех, кто разрабатывает приложения ReasonReact без помощи решений для управления состоянием на основе JS (например, Redux + Redux-Persist).
Начиная
Чтобы начать писать приложения ReasonReact Native, я предлагаю вам пойти по пути create-react-native-app
:
Предполагая, что у вас уже установлена последняя версия Node.js, запустите эти команды в своем терминале:
npm install -g create-react-native-app
create-react-native-app Switcheroo --scripts-version reason-react-native-scripts
cd Switcheroo
npm start
# preferably, I would prefix the prior command with `code . &&`
# to open it in VS Code before running the start script
# to prevent needing to do extra effort to open in your editor
Затем, как подробно описано в документации CRNA (по состоянию на 01.01.2018):
Установите« Expo на свой телефон iOS или Android и используйте QR-код в терминале, чтобы открыть свое приложение. Найдите QR-сканер на вкладке "Проекты" приложения ».
Строим UI
Теперь, когда наша среда разработки запущена и работает, пора перейти к самой интересной части и создать код!
Для начала вам нужно создать новый файл с именем Switcheroo.re
, который будет находиться в папке src
рядом с App.re
. Здесь мы создадим логику для нашего переключения.
В этом файле мы настраиваем основу для простого компонента RN Switch, обрабатывающего состояние с помощью строительного блока reducerComponent
, предоставленного в ReasonReact.
/* Switcheroo.re */
open BsReactNative;
type state = {toggled: bool};
type action =
| SetSwitchValue(bool);
let component = ReasonReact.reducerComponent("Switcheroo");
let make = (_children) => {
...component,
initialState: () => {toggled: false},
reducer: (action, _state) =>
switch action {
| SetSwitchValue(v) => ReasonReact.Update({toggled: v})
},
render: (self) =>
<Switch
value=self.state.toggled
onTintColor="#DD4C39"
onValueChange=((value) => self.reduce(() => SetSwitchValue(value), ()))
/>
};
В App.re
вы можете заменить внутреннюю часть View своим недавно написанным компонентом Switcheroo (код ниже).
/* App.re */
open BsReactNative;
let app = () =>
<View style=Style.(style([flex(1.), justifyContent(Center), alignItems(Center)]))>
<Switcheroo />
</View>;
Хорошо, милая, у нас есть крутой маленький переключатель, который мы можем переключать вперед и назад, но почему он не остается включенным, когда я снова открываю приложение? Ах да, мы забыли сохранить государство на местном уровне; Поехали!
Упорство
Чтобы сохранить состояние в React Native, необходимо использовать модуль AsyncStorage. Это позволяет вам установить сериализованные данные в долгосрочное хранилище данных и получить их позже, позволяя приложениям сохранять свои данные, даже если приложение было закрыто и перезапущено пользователем.
Ключевое слово в приведенном выше разделе - «сериализованный», что означает, что ваши данные должны быть преобразованы в строковый формат, чтобы быть сохраненными и восстановленными из строки и проанализированы обратно в живую структуру данных, чтобы использовать ее. в вашем приложении. Назовем это «кодированием» и «декодированием» нашего состояния.
Чтобы сделать это в ReasonML, нам нужно задействовать возможности bs-json
, которые предоставляют помощников для работы со структурами JSON.
- Во-первых, вам нужно запустить
npm i -S bs-json
, чтобы установить пакет. - Затем добавьте его в массив
bs-dependencies
вашего bsconfig.json. - Пока вы это делаете, измените свойство имени bsconfig.json на Switcheroo.
Когда вы закончите, bsconfig.json (файл конфигурации для цепочки инструментов BuckleScript, которая поддерживает вашу разработку ReasonML) должен выглядеть следующим образом:
{
"name": "Switcheroo",
"reason": {
"react-jsx": 2
},
"bsc-flags": ["-bs-super-errors"],
"bs-dependencies": ["bs-react-native", "reason-react", "bs-json"],
"sources": [
{
"dir": "src"
}
],
"refmt": 3
}
Теперь давайте создадим нашу persist
функцию и настроим ее на запуск, когда компонент обновляет состояние.
open BsReactNative;
type state = {toggled: bool};
type action =
| SetSwitchValue(bool);
let persist = state => {
/* convert state to JSON */
/* set it in RN's AsyncStorage */
()
};
let component = ReasonReact.reducerComponent("Switcheroo");
let make = (_children) => {
...component,
initialState: () => {toggled: false},
reducer: (action, _state) =>
switch action {
| SetSwitchValue(v) => ReasonReact.Update({toggled: v})
},
didUpdate: ({newSelf}) => persist(newSelf.state),
render: (self) =>
<Switch
value=self.state.toggled
onTintColor="#DD4C39"
onValueChange=((value) => self.reduce(() => SetSwitchValue(value), ()))
/>
};
Внутри этой функции нам нужно использовать bs-json
для кодирования нашего состояния в JSON и установить его в наше расположение AsyncStorage, а именно «Switcheroo.state».
/* Switcheroo.re (partial) */
let persist = (state) => {
/* convert state to JSON */
let stateAsJson =
Json.Encode.(object_([("toggled", Js.Json.boolean(Js.Boolean.to_js_boolean(state.toggled)))]))
|> Js.Json.stringify;
/* set it in RN's AsyncStorage */
AsyncStorage.setItem(
"Switcheroo.state",
stateAsJson,
~callback=
(e) =>
switch e {
| None => ()
| Some(err) => Js.log(err)
},
()
)
|> ignore
};
Итак, теперь, если вы проверите свое приложение сейчас и несколько раз переключите переключатель, вы обнаружите, что ничего не ломается (и это здорово!), Но когда вы обновите приложение, вы заметите, что ваше приложение все еще не работает. t продолжить с того места, где он остановился. Пора обновить ваше приложение!
Регидратация
Чтобы восстановить наше состояние, нам необходимо:
- создать действие регидратации, чтобы обновить состояние нашего reducerComponent
- создать
rehydrate
функцию, которая извлекает JSON из AsyncStorage и декодирует его обратно в запись ReasonML - установите компонент Switcheroo для вызова нашей
rehydrate
функции, когда компонент станет активным
Код, выполняющий перечисленные выше шаги, существует здесь:
/* Switcheroo.re */
open BsReactNative;
let storageKey = "Switcheroo.state";
type state = {toggled: bool};
type action =
| SetSwitchValue(bool)
| Rehydrate(state);
let persist = (state) => {
/* convert state to JSON */
let stateAsJson =
Json.Encode.(object_([("toggled", Js.Json.boolean(Js.Boolean.to_js_boolean(state.toggled)))]))
|> Js.Json.stringify;
/* set it in RN's AsyncStorage */
AsyncStorage.setItem(
storageKey,
stateAsJson,
~callback=
(e) =>
switch e {
| None => ()
| Some(err) => Js.log(err)
},
()
)
|> ignore
};
let rehydrate = (self) => {
Js.Promise.(
/* begin call to AsyncStorage */
AsyncStorage.getItem(storageKey, ())
|> then_(
(json) =>
(
switch json {
| None => ()
| Some(s) =>
/* parse JSON, decode it into a ReasonML Record, and reset the state */
let parsedJson = Js.Json.parseExn(s);
let state = Json.Decode.{toggled: parsedJson |> field("toggled", bool)};
self.ReasonReact.reduce(() => Rehydrate(state), ());
()
}
)
|> resolve
)
|> ignore
);
ReasonReact.NoUpdate
};
let component = ReasonReact.reducerComponent("Switcheroo");
let make = (_children) => {
...component,
initialState: () => {toggled: false},
reducer: (action, _state) =>
switch action {
| SetSwitchValue(v) => ReasonReact.Update({toggled: v})
| Rehydrate(s) => ReasonReact.Update(s)
},
didUpdate: ({newSelf}) => persist(newSelf.state),
didMount: (self) => rehydrate(self),
render: (self) =>
<Switch
value=self.state.toggled
onTintColor="#DD4C39"
onValueChange=((value) => self.reduce(() => SetSwitchValue(value), ()))
/>
};
Теперь у вас должно быть классное небольшое приложение, которое позволяет переключать переключатель в стиле ReasonML и сохранять его состояние. Милая!
Для более сложного примера сохранения и регидратации состояния JSON в ReasonML ознакомьтесь с кодом, который я написал для своего личного фитнес-трекера здесь.
Надеюсь, вы многому научились из этого поста и получили удовольствие, читая его! Чтобы узнать больше, подписывайтесь на меня в Twitter! Это самый простой способ связаться со мной и узнать о новых вещах, которые я делаю, новых идеях, которые я изучаю, или новых методах, которые я изучаю!
Всего хорошего!
- Джуван