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)
  }
  

  // ...
}