根据 Promise 调用 React hook
Call React hook depending on Promise
我在 AsyncStorage 中存储了一个 ID,根据这个调用,我想发出一个服务器请求。
所以需要这样的东西:
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 只是调用另一个 hook UseLoadFromEndpoint
做 axios.get()
当尝试将 AsyncStorage-Request 移动到 customHook 时,我遇到了同样的错误,因为我错误地调用了 useLoadFromEndpoint
-hook,但我必须/想要重用 UseLoadFromEndpoint-Hook。我怎样才能做到这一点?
hooks 规则规定所有 hooks 必须 运行 在每个渲染周期中以相同的顺序。这意味着我们需要以特定方式编写条件逻辑。我会推荐这个。
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
。所有 React 组件都应该 return 从你的组件中得到 return null
这样的东西,它应该可以解决你的问题。此外,为避免不必要的渲染,您应该在 useEffect 中使用空数组进行渲染,这样它只会触发一次(在组件安装后)。
您需要修改 useLoadRoot
挂钩或将该逻辑包装在子组件中。挂钩不允许有条件地使用。
路线 1:重写 useLoadRoot
const useLoadRoot = (id) => {
const getRoot = async (rootId) => ...;
const [root, setRoot] = useState();
useEffect(() => {
if (id != undefined) {
await getRoot(id);
}
}, [id]);
return root;
}
这只是实现您想要的目标的一种方法。您可以传入一个 enabled 属性,它是一个布尔值,只有在为真时才允许请求。例如,这是在 react-query 中使用的方法(参见:docs)。
路线二:条件子组件
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);
...
}
我在 AsyncStorage 中存储了一个 ID,根据这个调用,我想发出一个服务器请求。
所以需要这样的东西:
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 只是调用另一个 hook UseLoadFromEndpoint
做 axios.get()
当尝试将 AsyncStorage-Request 移动到 customHook 时,我遇到了同样的错误,因为我错误地调用了 useLoadFromEndpoint
-hook,但我必须/想要重用 UseLoadFromEndpoint-Hook。我怎样才能做到这一点?
hooks 规则规定所有 hooks 必须 运行 在每个渲染周期中以相同的顺序。这意味着我们需要以特定方式编写条件逻辑。我会推荐这个。
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
。所有 React 组件都应该 return 从你的组件中得到 return null
这样的东西,它应该可以解决你的问题。此外,为避免不必要的渲染,您应该在 useEffect 中使用空数组进行渲染,这样它只会触发一次(在组件安装后)。
您需要修改 useLoadRoot
挂钩或将该逻辑包装在子组件中。挂钩不允许有条件地使用。
路线 1:重写 useLoadRoot
const useLoadRoot = (id) => {
const getRoot = async (rootId) => ...;
const [root, setRoot] = useState();
useEffect(() => {
if (id != undefined) {
await getRoot(id);
}
}, [id]);
return root;
}
这只是实现您想要的目标的一种方法。您可以传入一个 enabled 属性,它是一个布尔值,只有在为真时才允许请求。例如,这是在 react-query 中使用的方法(参见:docs)。
路线二:条件子组件
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);
...
}