使用 useReducer 时如何从 AsyncStorage 获取数据并将其添加到初始状态?
How can I get data from AsyncStorage and add it to initial state when using useReducer?
我正在使用来自 Hooks 的 useContext & useReducer & AsyncStorage.setItem在 useEffect 中保存状态更新时的数据。在应用程序重新加载时,我想确保使用 AsyncStorage.getItem 获取保存的数据并将其添加到初始状态。
我尝试将带有异步的 init 函数作为第三个 属性 添加到 useReducer,但它仍然没有用接收到的数据替换初始数据。请阅读以下代码并提供帮助。
提前致谢!
我可以将数据保存到 AsyncStorage 的当前代码
const [user, dispatch] = useReducer(userReducer, {});
useEffect(() => {
AsyncStorage.setItem('user', JSON.stringify(user))
}, [user]);
return(
<UserContext.Provider value={{user,dispatch}}>
{props.children}
</UserContext.Provider>
);
}
下面是我试过的代码,但无法将现有数据保存为初始数据。
const getUser = async function() {
const userData = await AsyncStorage.getItem('user')
console.log("parse");
console.log(userData);
console.log("parsed data");
console.log(JSON.parse(userData));
return userData ? JSON.parse(userData) : {};
}
export const UserContext = createContext();
const UserContextProvider = (props) => {
const [user, dispatch] = useReducer(userReducer, {}, getUser);
useEffect(() => {
console.log("context");
console.log(JSON.stringify(user));
AsyncStorage.setItem('user', JSON.stringify(user))
}, [user]);
return(
<UserContext.Provider value={{user,dispatch}}>
{props.children}
</UserContext.Provider>
);
}
您的使用Reducer 的初始状态需要同步。由于 asyncStorage 不是同步的 API 您实际上不能将值作为 initialState
传递
但是您可以像下面那样使用 useEffect loading state
const getUser = async () => {
try {
const user = await AsyncStorage.getItem('user')
return user ? JSON.parse(user) : {};
} catch (e) {
console.log('Failed to fetch the data from storage');
}
}
export const UserContext = createContext();
const UserContextProvider = (props) => {
const [isLoading, setIsLoading] = useState(true);
const [user, dispatch] = useReducer(userReducer, {});
// Loading initial Satte
useEffect(() => {
async function fetchUser() {
const user = await getUser();
setIsLoading(false);
dispatch({type: 'INIT_REDUCER', user}); // You must handle initReducer in reducer
}
fetchUser();
}, []);
useEffect(() => {
if(user) {
// This check is required to avoid initial writing to asyncStorage
console.log("context");
console.log(JSON.stringify(user));
AsyncStorage.setItem('user', JSON.stringify(user))
}
}, [user]);
if(isLoading) {
return (
<View>
<Text>Loading...</Text>
</View>
);
}
return(
<UserContext.Provider value={{user,dispatch}}>
{props.children}
</UserContext.Provider>
);
}
谢谢!
根据以下建议更新和工作代码并进行了细微更改。
const getUser = async () => {
try {
const user = await AsyncStorage.getItem('user')
return user ? JSON.parse(user) : {};
} catch (e) {
console.log('Failed to fetch the data from storage');
}
}
export const UserContext = createContext();
const UserContextProvider = (props) => {
const [user, dispatch] = useReducer(userReducer, {});
// Loading initial Satte
useEffect(() => {
async function fetchUser() {
const user = await getUser();
dispatch({type: 'ADD_USER', user});
}
fetchUser();
}, []);
// Update AsyncStorage when user is updated
useEffect(() => {
// This check is required to avoid initial writing to asyncStorage
if(user) {
AsyncStorage.setItem('user', JSON.stringify(user))
}
}, [user]);
return(
<UserContext.Provider value={{user,dispatch}}>
{props.children}
</UserContext.Provider>
);
}
我正在使用来自 Hooks 的 useContext & useReducer & AsyncStorage.setItem在 useEffect 中保存状态更新时的数据。在应用程序重新加载时,我想确保使用 AsyncStorage.getItem 获取保存的数据并将其添加到初始状态。
我尝试将带有异步的 init 函数作为第三个 属性 添加到 useReducer,但它仍然没有用接收到的数据替换初始数据。请阅读以下代码并提供帮助。
提前致谢!
我可以将数据保存到 AsyncStorage 的当前代码
const [user, dispatch] = useReducer(userReducer, {});
useEffect(() => {
AsyncStorage.setItem('user', JSON.stringify(user))
}, [user]);
return(
<UserContext.Provider value={{user,dispatch}}>
{props.children}
</UserContext.Provider>
);
}
下面是我试过的代码,但无法将现有数据保存为初始数据。
const getUser = async function() {
const userData = await AsyncStorage.getItem('user')
console.log("parse");
console.log(userData);
console.log("parsed data");
console.log(JSON.parse(userData));
return userData ? JSON.parse(userData) : {};
}
export const UserContext = createContext();
const UserContextProvider = (props) => {
const [user, dispatch] = useReducer(userReducer, {}, getUser);
useEffect(() => {
console.log("context");
console.log(JSON.stringify(user));
AsyncStorage.setItem('user', JSON.stringify(user))
}, [user]);
return(
<UserContext.Provider value={{user,dispatch}}>
{props.children}
</UserContext.Provider>
);
}
您的使用Reducer 的初始状态需要同步。由于 asyncStorage 不是同步的 API 您实际上不能将值作为 initialState
传递但是您可以像下面那样使用 useEffect loading state
const getUser = async () => {
try {
const user = await AsyncStorage.getItem('user')
return user ? JSON.parse(user) : {};
} catch (e) {
console.log('Failed to fetch the data from storage');
}
}
export const UserContext = createContext();
const UserContextProvider = (props) => {
const [isLoading, setIsLoading] = useState(true);
const [user, dispatch] = useReducer(userReducer, {});
// Loading initial Satte
useEffect(() => {
async function fetchUser() {
const user = await getUser();
setIsLoading(false);
dispatch({type: 'INIT_REDUCER', user}); // You must handle initReducer in reducer
}
fetchUser();
}, []);
useEffect(() => {
if(user) {
// This check is required to avoid initial writing to asyncStorage
console.log("context");
console.log(JSON.stringify(user));
AsyncStorage.setItem('user', JSON.stringify(user))
}
}, [user]);
if(isLoading) {
return (
<View>
<Text>Loading...</Text>
</View>
);
}
return(
<UserContext.Provider value={{user,dispatch}}>
{props.children}
</UserContext.Provider>
);
}
谢谢! 根据以下建议更新和工作代码并进行了细微更改。
const getUser = async () => {
try {
const user = await AsyncStorage.getItem('user')
return user ? JSON.parse(user) : {};
} catch (e) {
console.log('Failed to fetch the data from storage');
}
}
export const UserContext = createContext();
const UserContextProvider = (props) => {
const [user, dispatch] = useReducer(userReducer, {});
// Loading initial Satte
useEffect(() => {
async function fetchUser() {
const user = await getUser();
dispatch({type: 'ADD_USER', user});
}
fetchUser();
}, []);
// Update AsyncStorage when user is updated
useEffect(() => {
// This check is required to avoid initial writing to asyncStorage
if(user) {
AsyncStorage.setItem('user', JSON.stringify(user))
}
}, [user]);
return(
<UserContext.Provider value={{user,dispatch}}>
{props.children}
</UserContext.Provider>
);
}