更新 useState 和 AsyncStorage 并根据给定结果重新渲染屏幕
Updating useState and AsyncStorage and Rerendering the screen based on given result
我是 React Native 的新手,我目前正在尝试从网站获取凭据数据并将其保存到设备内存中。但是我遇到了一些关于它的问题!
我的流量:
启动应用程序时,应用程序将检查 asyncStorage 是否有凭据。
如果是这样,我们直接进入应用程序。否则我们进入 RootStackScreen(又名登录屏幕)***(问题 #1)
(LOGIN) 用户将输入 his/her 登录到将保存在 useState 中的文本输入。
使用函数 'loginHandle' 使用来自 useState 的信息调用获取请求,我们使用数据 returned.**(问题 #2)
应用程序应重新呈现并看到有凭据并加载到主屏幕。 ***(第 3 期)
但是,我遇到了 2 个问题。
*** 即使当我在 return(...) 中检查 appLoad.credentials 时 asyncStorage 确实包含凭据,它 return 也是空的。但是,它 return 在我的 useEffect() 中是正确的值。我想通过使用 useEffect() 我在屏幕渲染之前的 ComponentsDidMount 期间调用函数。那么 appLoad.credentials 不应该包含一个字符串吗?
在我的console.log(credential)上总是落后一步。 IE。我按一次登录按钮。控制台日志将 return 为空。但是,我认为由于 console.log() 在获取命令之后,因此应该在 console.log 调用之前设置凭据!
如何让应用程序重新呈现。我在网上看到有关强制重新渲染的内容,但我听说这很糟糕!
App.js
import AsyncStorage from '@react-native-community/async-storage';
...
export default function App() {
const STORAGE_KEY = '@deviceCredentials';
const [data, setData] = useState('');
const appLoad = {
isLoading: true,
credentials: null
};
//Runs during ComponentsDidMount
useEffect(() => {
setTimeout(async () => {
//In 1000ms try to get credentials
try {
appLoad.credentials = await AsyncStorage.getItem(STORAGE_KEY);
console.log(appLoad.credentials);
} catch (e) {
console.log(e);
}
}, 1000);
}, []);
//Render
return (
<NavigationContainer>
{/* If credentials is not null then we can go straight into Main screen,
otherwise we go to Login Screen */}
{appLoad.credentials !== null ? (
<Drawer.Navigator drawerContent={props => <DrawerContent {...props} />}>
<Drawer.Screen name="MusteringDrawer" component={MainTabScreen} />
</Drawer.Navigator>
)
:
<RootStackScreen />
}
</NavigationContainer>
);
};
SignIn.js
...
...
const [data, setData] = useState({
username: '',
password: '',
...
})
const [credential, setCredential] = useState({ data: null });
const STORAGE_KEY = '@deviceCredentials';
...
...
//Handles user data
const handleValidUser = (val) => {
setData({
...data,
username: val,
});
}
const loginHandle = () => {
fetch(url + data.password + data.username)
.then(x => x.text())
.then(y => {
setCredential({ data: y });
});
console.log(credential);
AsyncStorage.setItem(STORAGE_KEY, credential);
}
return(
<Text>Username</Text>
<TextInput
placeholder="Your Username"
onChangeText={(val) => handleValidUser(val)}
onEndEditing={(e) => handleValidUser(e.nativeEvent.text)}
/>
<Text>Password</Text>
<TextInput
placeholder="Your Password"
onChangeText={(val) => handlePasswordChange(val)}
/>
<View style={styles.button}>
<TouchableOpacity onPress={() => { loginHandle(); }}>
<Text>Sign In</Text>
</TouchableOpacity>
</View>
您是否知道以下事实:
const appLoad = {
isLoading: true,
credentials: null
};
每次渲染都重新定义?更重要的是,如果在 effect hook 中设置了值,react 无法知道它已更改,因此不会重新渲染。如果它确实重新渲染(出于某些完全不同的原因,这个 将不会 重新渲染)...好吧,新变量 :D.
你想要的是在所有渲染中记住这样的数据。您肯定知道,您可以通过使用 useState
挂钩来执行此操作。
免责声明:阅读我在代码中添加的注释非常重要,它们对于 work/be“最佳实践”至关重要。此代码也未经过测试,但您应该能够使用您的一些出色的开发技能使其正常工作:)
export default function App() {
// Remove this, seems to be a leftover from testing
// const [data, setData] = useState('');
const [isLoading, setIsLoading] = useState(true);
const [credentials, setCredentials] = useState(null);
// Check for credentials in the first render
useEffect(() => {
// 1. I'm not sure why you add a delay, It will probably only make your app appear sluggish
// 2. Use effect callbacks should not be made async, see this post
//
async function fetchCredentials() {
setCredentials(await AsyncStorage.getItem(STORAGE_KEY));
setIsLoading(false);
}
fetchCredentials();
}, []);
// Whatever your render code may be
return null;
}
很可能是我没有解决你的问题(我可能没有理解你,而且大多数时候我一般都有点傻)。在这种情况下,请不要犹豫,通过评论与我联系。
干杯,编码愉快!
我是 React Native 的新手,我目前正在尝试从网站获取凭据数据并将其保存到设备内存中。但是我遇到了一些关于它的问题!
我的流量:
启动应用程序时,应用程序将检查 asyncStorage 是否有凭据。
如果是这样,我们直接进入应用程序。否则我们进入 RootStackScreen(又名登录屏幕)***(问题 #1)
(LOGIN) 用户将输入 his/her 登录到将保存在 useState 中的文本输入。
使用函数 'loginHandle' 使用来自 useState 的信息调用获取请求,我们使用数据 returned.**(问题 #2)
应用程序应重新呈现并看到有凭据并加载到主屏幕。 ***(第 3 期)
但是,我遇到了 2 个问题。
*** 即使当我在 return(...) 中检查 appLoad.credentials 时 asyncStorage 确实包含凭据,它 return 也是空的。但是,它 return 在我的 useEffect() 中是正确的值。我想通过使用 useEffect() 我在屏幕渲染之前的 ComponentsDidMount 期间调用函数。那么 appLoad.credentials 不应该包含一个字符串吗?
在我的console.log(credential)上总是落后一步。 IE。我按一次登录按钮。控制台日志将 return 为空。但是,我认为由于 console.log() 在获取命令之后,因此应该在 console.log 调用之前设置凭据!
如何让应用程序重新呈现。我在网上看到有关强制重新渲染的内容,但我听说这很糟糕!
App.js
import AsyncStorage from '@react-native-community/async-storage';
...
export default function App() {
const STORAGE_KEY = '@deviceCredentials';
const [data, setData] = useState('');
const appLoad = {
isLoading: true,
credentials: null
};
//Runs during ComponentsDidMount
useEffect(() => {
setTimeout(async () => {
//In 1000ms try to get credentials
try {
appLoad.credentials = await AsyncStorage.getItem(STORAGE_KEY);
console.log(appLoad.credentials);
} catch (e) {
console.log(e);
}
}, 1000);
}, []);
//Render
return (
<NavigationContainer>
{/* If credentials is not null then we can go straight into Main screen,
otherwise we go to Login Screen */}
{appLoad.credentials !== null ? (
<Drawer.Navigator drawerContent={props => <DrawerContent {...props} />}>
<Drawer.Screen name="MusteringDrawer" component={MainTabScreen} />
</Drawer.Navigator>
)
:
<RootStackScreen />
}
</NavigationContainer>
);
};
SignIn.js
...
...
const [data, setData] = useState({
username: '',
password: '',
...
})
const [credential, setCredential] = useState({ data: null });
const STORAGE_KEY = '@deviceCredentials';
...
...
//Handles user data
const handleValidUser = (val) => {
setData({
...data,
username: val,
});
}
const loginHandle = () => {
fetch(url + data.password + data.username)
.then(x => x.text())
.then(y => {
setCredential({ data: y });
});
console.log(credential);
AsyncStorage.setItem(STORAGE_KEY, credential);
}
return(
<Text>Username</Text>
<TextInput
placeholder="Your Username"
onChangeText={(val) => handleValidUser(val)}
onEndEditing={(e) => handleValidUser(e.nativeEvent.text)}
/>
<Text>Password</Text>
<TextInput
placeholder="Your Password"
onChangeText={(val) => handlePasswordChange(val)}
/>
<View style={styles.button}>
<TouchableOpacity onPress={() => { loginHandle(); }}>
<Text>Sign In</Text>
</TouchableOpacity>
</View>
您是否知道以下事实:
const appLoad = {
isLoading: true,
credentials: null
};
每次渲染都重新定义?更重要的是,如果在 effect hook 中设置了值,react 无法知道它已更改,因此不会重新渲染。如果它确实重新渲染(出于某些完全不同的原因,这个 将不会 重新渲染)...好吧,新变量 :D.
你想要的是在所有渲染中记住这样的数据。您肯定知道,您可以通过使用 useState
挂钩来执行此操作。
免责声明:阅读我在代码中添加的注释非常重要,它们对于 work/be“最佳实践”至关重要。此代码也未经过测试,但您应该能够使用您的一些出色的开发技能使其正常工作:)
export default function App() {
// Remove this, seems to be a leftover from testing
// const [data, setData] = useState('');
const [isLoading, setIsLoading] = useState(true);
const [credentials, setCredentials] = useState(null);
// Check for credentials in the first render
useEffect(() => {
// 1. I'm not sure why you add a delay, It will probably only make your app appear sluggish
// 2. Use effect callbacks should not be made async, see this post
//
async function fetchCredentials() {
setCredentials(await AsyncStorage.getItem(STORAGE_KEY));
setIsLoading(false);
}
fetchCredentials();
}, []);
// Whatever your render code may be
return null;
}
很可能是我没有解决你的问题(我可能没有理解你,而且大多数时候我一般都有点傻)。在这种情况下,请不要犹豫,通过评论与我联系。
干杯,编码愉快!