mobx+react native 中的无效钩子调用
invalid hook call in mobx+react native
我是 mobx 的新手,
我被告知我不能直接从rootStore.tsx
直接使用rootStore
,我必须用hook替换它,所以我尝试调用hook useStore
来自 rootStore.tsx
但在这种情况下我得到了一个错误“无效的钩子调用。钩子可以在主体内部调用”
我的文件是:
rootStore.tsx
import { createContext, useContext } from 'react'
import { makeAutoObservable } from 'mobx'
import { AsyncTrunk } from 'mobx-sync'
import AsyncStorage from '@react-native-async-storage/async-storage'
import { DayStyle, firstDayStyle } from '../styles/markedDayStyle'
const period: Record<string, DayStyle> = {
'2022-02-16': firstDayStyle,
}
export const rootStore = makeAutoObservable({
periods: period,
})
export const trunk = new AsyncTrunk(rootStore, {
storage: AsyncStorage,
})
export const StoreContext = createContext(rootStore)
export const StoreProvider = StoreContext.Provider
export const useStore = () => useContext(StoreContext)
App.tsx
const App = observer(({}) => {
const store = useStore()
const [isStoreLoaded, setIsStoreLoaded] = useState(false)
useEffect(() => {
const rehydrate = async () => {
await trunk.init()
setIsStoreLoaded(true)
}
rehydrate().catch(() => console.log('problems with localStorage'))
}, [store])
if (!isStoreLoaded) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<ActivityIndicator size="large" />
</View>
)
} else {
return (
<StoreProvider value={store}>
<PaperProvider theme={store.isDarkMode ? darkTheme : lightTheme}>
<View style={styles.container}>
<CalendarScreen/>
</View>
</PaperProvider>
</StoreProvider>
)
}
})
CalendarScreen.tsx
const CalendarScreen = observer(({}) => {
const store = useStore()
const handleDayPress = (day: DateData) => {
setModalVisible(true)
setPressedDay(day.dateString)
}
return (
<SafeAreaView style={styles.screenContainer}>
<Calendar
onDayPress={day => {handleDayPress(day)}}
/>
<View>
<ModalConfirmDay modalVisible={modalVisible} setModalVisible={setModalVisible} pressedDay={pressedDay} />
</View>
</SafeAreaView>
)
)}
ModalConfirmDay.tsx
import { fillMarkedDays } from '../functions/fillMarkedDays'
const ModalConfirmDay = observer(({ modalVisible, setModalVisible, pressedDay }: ModalConfirmDayProps) => {
const handlePeriodStarts = () => {
fillMarkedDays(pressedDay)
setModalVisible(false)
}
return (
<View style={styles.centeredView}>
<Modal
visible={modalVisible}
>
<View style={styles.modalView}>
<TouchableOpacity onPress={() => handlePeriodStarts()}>
<Text>Period starts</Text>
</TouchableOpacity>
</View>
</Modal>
</View>
)
})
fillMarkedDays.tsx
import { rootStore, useStore} from '../store/rootStore'
import { firstDayStyle} from '../styles/markedDayStyle'
const fillMarkedDays = (selectedDay: string) => {
const store = useStore()
if (selectedDay) {
store.periods[selectedDay] = firstDayStyle
}
}
当我尝试将新键值(在 fillMarkedDays.tsx
中)添加到 store.periods
时,我得到了这个
我该如何解决这个问题或 select 一种更好的调用商店的方法?谢谢大家
By the rules of hooks 你不能在函数体(组件)之外使用钩子,所以基本上你只能在 return 语句之前使用它们,而且你也不能使用任何条件等等。 fillMarkedDays
只是一个函数,不是组件,它无法访问 React 上下文、钩子或其他任何东西。
你可以做的是先用 hook 获取商店,然后将它作为参数传递给 fillMarkedDays
函数:
const ModalConfirmDay = observer(({ modalVisible, setModalVisible, pressedDay }: ModalConfirmDayProps) => {
const store = useStore()
const handlePeriodStarts = () => {
fillMarkedDays(store, pressedDay)
setModalVisible(false)
}
// ...
}
我是 mobx 的新手,
我被告知我不能直接从rootStore.tsx
直接使用rootStore
,我必须用hook替换它,所以我尝试调用hook useStore
来自 rootStore.tsx
但在这种情况下我得到了一个错误“无效的钩子调用。钩子可以在主体内部调用”
我的文件是:
rootStore.tsx
import { createContext, useContext } from 'react'
import { makeAutoObservable } from 'mobx'
import { AsyncTrunk } from 'mobx-sync'
import AsyncStorage from '@react-native-async-storage/async-storage'
import { DayStyle, firstDayStyle } from '../styles/markedDayStyle'
const period: Record<string, DayStyle> = {
'2022-02-16': firstDayStyle,
}
export const rootStore = makeAutoObservable({
periods: period,
})
export const trunk = new AsyncTrunk(rootStore, {
storage: AsyncStorage,
})
export const StoreContext = createContext(rootStore)
export const StoreProvider = StoreContext.Provider
export const useStore = () => useContext(StoreContext)
App.tsx
const App = observer(({}) => {
const store = useStore()
const [isStoreLoaded, setIsStoreLoaded] = useState(false)
useEffect(() => {
const rehydrate = async () => {
await trunk.init()
setIsStoreLoaded(true)
}
rehydrate().catch(() => console.log('problems with localStorage'))
}, [store])
if (!isStoreLoaded) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<ActivityIndicator size="large" />
</View>
)
} else {
return (
<StoreProvider value={store}>
<PaperProvider theme={store.isDarkMode ? darkTheme : lightTheme}>
<View style={styles.container}>
<CalendarScreen/>
</View>
</PaperProvider>
</StoreProvider>
)
}
})
CalendarScreen.tsx
const CalendarScreen = observer(({}) => {
const store = useStore()
const handleDayPress = (day: DateData) => {
setModalVisible(true)
setPressedDay(day.dateString)
}
return (
<SafeAreaView style={styles.screenContainer}>
<Calendar
onDayPress={day => {handleDayPress(day)}}
/>
<View>
<ModalConfirmDay modalVisible={modalVisible} setModalVisible={setModalVisible} pressedDay={pressedDay} />
</View>
</SafeAreaView>
)
)}
ModalConfirmDay.tsx
import { fillMarkedDays } from '../functions/fillMarkedDays'
const ModalConfirmDay = observer(({ modalVisible, setModalVisible, pressedDay }: ModalConfirmDayProps) => {
const handlePeriodStarts = () => {
fillMarkedDays(pressedDay)
setModalVisible(false)
}
return (
<View style={styles.centeredView}>
<Modal
visible={modalVisible}
>
<View style={styles.modalView}>
<TouchableOpacity onPress={() => handlePeriodStarts()}>
<Text>Period starts</Text>
</TouchableOpacity>
</View>
</Modal>
</View>
)
})
fillMarkedDays.tsx
import { rootStore, useStore} from '../store/rootStore'
import { firstDayStyle} from '../styles/markedDayStyle'
const fillMarkedDays = (selectedDay: string) => {
const store = useStore()
if (selectedDay) {
store.periods[selectedDay] = firstDayStyle
}
}
当我尝试将新键值(在 fillMarkedDays.tsx
中)添加到 store.periods
时,我得到了这个
我该如何解决这个问题或 select 一种更好的调用商店的方法?谢谢大家
By the rules of hooks 你不能在函数体(组件)之外使用钩子,所以基本上你只能在 return 语句之前使用它们,而且你也不能使用任何条件等等。 fillMarkedDays
只是一个函数,不是组件,它无法访问 React 上下文、钩子或其他任何东西。
你可以做的是先用 hook 获取商店,然后将它作为参数传递给 fillMarkedDays
函数:
const ModalConfirmDay = observer(({ modalVisible, setModalVisible, pressedDay }: ModalConfirmDayProps) => {
const store = useStore()
const handlePeriodStarts = () => {
fillMarkedDays(store, pressedDay)
setModalVisible(false)
}
// ...
}