Как направить навигацию с помощью xState в приложении React Native
Я новичок в xState и хочу перенести свое существующее приложение с redux на xState(мой основной мотив - полностью избавиться от кода redux из приложения), чтобы сделать это, я перешел по некоторым ссылкам, но застрял в части навигации. Позвольте мне объяснить, то, что я пытаюсь достичь с помощью xState, по следующему сценарию: у меня есть три файла в моем коде homeScreen.js, searchResult.js и myMachine.js, которые содержат логику состояния. Главный экран содержит несколько полей ввода и кнопку поиска, когда пользователь нажимает кнопку поиска, он вызывает API, и в случае успешного получения результата перемещается по экрану результатов и передает результат на экран результатов.
myMachine.js // содержащие машинную логику
import { Machine } from "xstate"
const persist = [(ctx, e) => {
try {
ctx.searchFormData = e.formData || ctx.searchFormData
ctx.currentSearchPage = e.currentSearchPage || ctx.currentSearchPage
switch (e.type) {
case "done.invoke.call-search-api":
ctx.searchResults = e.data && e.data.results
break
default:
console.log("> Non-persisted event: ", e.type)
break
}
} catch (err) {
console.log('Error in Persist context: '+err)
}
}]
const searchResultsLoadedEvents = {
MORE_SEARCH_RESULTS: {
target: "searchResultsPaginating",
actions: [...persist],
},
}
const states = {
formVisible: {
on: {
SUBMIT: {
target: "searchResultsLoading",
actions: [...persist],
}
},
entry: ["retrievePreviousContext", "setInitialContext"],
},
searchResultsLoading: {
invoke: {
id: "call-search-api",
src: "callSearchAPI",
onDone: {
target: "searchResultsLoaded",
actions: [...persist],
},
},
on: {},
entry: ["logSearchFormData"],
},
searchResultsLoaded: {
entry: ["loadSearchResults", "incrementCurrentSearchPage"],
on: searchResultsLoadedEvents
}
}
const myMachine = Machine({
id: 'machineFirst',
initial: "formVisible",
states
})
export default myMachine
Главный экран /index.js
import myMachine from "./myMachine" import {Navigation} from "react-native-navigation"; import {useMachine} from "@xstate/react" const Home = props => { const [current, send] = useMachine(myMachine) const state = current.value const context = current.context if (current.context.searchResults && current.context.searchResults.data && current.context.searchResults.data.length > 0) { Navigation.push(props.componentId, { component: {name: "screen.SearchResult"}}) // which i am trying to rid of redux and want to use xState navigation } return ( <Container style={{marginTop: 10, marginHorizontal: 15}}> {/* here i have some input fields and search button on tapping on search button tap, i call send("SUBMIT",{form body param}) of machine code*/} </Container> )} export default Home;
3.searchResult.js
import React, { useEffect} from "react";
import {useMachine} from "@xstate/react"
import myMachine from "./myMachine"
import {View} from "react-native";
const SearchResult = props => {
const [current, send] = useMachine(myMachine) // when i use this line it will reset state to initial state "formVisible" even my last state was "searchResultsLoaded" and it also clear the context data
const state = current.value
const context = current.context
useEffect(() => {
if(current && current.value && current.value === 'searchResultsLoaded'){
// assign the response result which i am getting as an response of search api call
}
}, [current.value ]);
return(
<View style={[{flex: 1, backgroundColor: '#f8f9fb'}]}>
{/*here i show the list */}
</View>
)
}
export default SearchResult
В приведенном выше коде у меня есть еще несколько сомнений, которые перечислены ниже:
- Нужно ли мне создавать отдельную машину для каждого экрана?
- Если да, то как я могу управлять отдельными машинами для каждого экрана?
- Если нет, то как мне создать экземпляр машины (который не сбрасывает машину до ее начального значения состояния), который я могу совместно использовать или использовать с каждым экраном с сохранением / удержанием последнего перехода состояния и сохраненного значения контекста?
- Как управлять навигацией по экранам с помощью xState?
Примечание. Для этого я уже перешел по этой ссылке, которая не работает https://codesandbox.io/s/ykmykxnm3z.
Заранее спасибо.