根据Promise调用React钩子



我有一个ID存储在AsyncStorage和依赖于这个调用,我想做一个服务器请求。

所以需要这样的东西:

AsyncStorage.getID().then(id => {
useLoadFromServer(id)
}

但是我总是纠结于错误地使用钩子。到目前为止,我尝试了:

// First Approach
const MyScreen = () => {
const [ID, setID] = useState()
AsyncStorage.getID()
.then(id => setID(id))
.catch(e => console.log(e))

const { data } = useLoadRoot(ID) // Not the ID from AsyncStorage is used
}
//Second Approach
const MyScreen = async () => {
const [ID, setID] = useState()
const IDPromise = AsyncStorage.getID()
const { data } = useLoadRoot(await IDPromise) // Possible Unhandled Promise Rejection

我也尝试使用useEffect,这导致React Hooks must be called in a React function component or a custom React Hook function

useLoadRoot-hook只是调用另一个钩子UseLoadFromEndpoint执行axios.get()

当试图将AsyncStorage-Request移动到customHook时,我得到了相同的错误,因为我错误地调用了useLoadFromEndpoint-hook,但我必须/想要重用useloadfromendpointhook。我怎样才能做到这一点呢?

您需要修改useLoadRoot钩子或将该逻辑包装在子组件中。钩子不允许有条件地使用。

Route 1: RewriteuseLoadRoot

const useLoadRoot = (id) => {
const getRoot = async (rootId) => ...;
const [root, setRoot] = useState();
useEffect(() => {
if (id != undefined) { 
await getRoot(id);
}
}, [id]);
return root;
}

这只是实现你想要的一种方法。您可以传入一个enabled属性,该属性是一个布尔值,只有在为true时才允许请求。这是在react-query中使用的方法,例如(参见:docs)。

路由2:条件子组件

const Parent = () => {
const [ID, setID] = useState()

useEffect(() => {
AsyncStorage.getID()
.then(id => setID(id))
.catch(e => console.log(e))
}, []);
return ID ? <WithFetchRoot rootId={ID}/> : null; //could be a loader component instead of null
}
const WithFetchRoot = (id) => {
const root = useLoadRoot(ID);
...
}

钩子规则规定所有钩子必须在每个呈现周期中以相同的顺序运行。这意味着我们需要以一种特殊的方式来编写条件逻辑。我推荐这个。

const MyScreen = () => {
const [ID, setID] = useState()
cosnt [data, setData] = useState()
useEffect(() => {
const getData = async () => {
const id = await AsyncStorage.getID()
setID(id)
const { data } = useLoadRoot(id)
setData(data)
}
getData()
})

if (data) {
// do stuff
}
return null
}

这是因为你没有return。所有的反应组件应该返回一些东西,所以从你的组件返回null,它应该解决你的问题。另外,为了避免不必要的渲染,你应该在useEffect中使用一个空数组,这样它只获得一次触发器(在组件挂载之后)。

最新更新