如何解决由于使用状态,React Native中的无限循环
我有1 /使用useState来保存axios请求中的数据的无限循环。 我想在映射过程中在视图中注入值:
import { StyleSheet,Text,View,TextInput,FlatList,Button,ScrollView } from 'react-native';
import styles from './styles'
import React,{ useEffect,useState,Component } from 'react';
import App,{ currentCityCode } from './app'
import axios from 'axios';
import { Dropdown } from 'react-native-material-dropdown';
function Chat(props) {
useEffect(() => {
getMessage()
},[]
);
const messApiRest = "https://..."
const [lastMessage,setLastMessage] = useState("")
const [user,setUser] = useState("")
const [categoryMessage,setcategoryMessage] = useState("")
const [idUser,setIdUser] = useState("")
const [allMessages,setAllMessages] = useState([])
const [messageOneByOne,seMessageOneByOne] = useState([])
function getMessage() {
axios.get(messApiRest + "/api/messages",{
headers: {
'Authorization': "Bearer " + props.token,},params: {
'citycode': props.cityCode
},})
.then(response => {
setAllMessages(response.data.results)
},)
}
function getUserName(toto) {
axios.get(messApiRest + "/api/users/" + toto,}
}
)
.then(response => {
console.log(response.data.username)
setUser(response.data.username)
})
}
return (
<View style={styles.container}>
{allMessages.map(function (message) {
getUserName(message.author.id)
return (
<Text>{user}: {message.content}</Text>
)
})}
</View>
)
}
export default Chat
主要问题是,如果使用useState保存我的{user},我会创建一个无限循环。
2 /我尝试通过不将其保存为useState来避免这种情况,并直接在视图中返回值response.data.username,但这是行不通的。我知道我无法返回诺言的价值,这就是为什么我改用useState的原因。
我是一个乞{{可能不是一个好人},我试图了解React和axios的工作原理,但是我已达到极限,无法猜测解决方案...
如果有人敢^^
,谢谢您的帮助解决方法
这里的中心问题是每个渲染器都调用getUserName
,这反过来会设置状态,从而触发另一个渲染器。
render => getUserName => setUser => render => getUserName => setUser => render
一种解决方案是创建一个单独的用户名组件来处理名称解析:
const DisplayName = ({userid}) => {
const [displayName,setDisplayName] = useState();
useEffect(() => {
// resolve username and call setDisplayName
},[userid]);
return (
<span>{displayName}</span>
);
}
然后您可以传递作者ID并对其进行处理:
return (
<View style={styles.container}>
{allMessages.map(message => (
<Text>
<DisplayName userid={message.author.id} />: {message.content}
</Text>
))
}
</View>
)
仍然存在为聊天中的每条消息重新获取用户名的问题,但这解决了无限循环问题。
要解决重复的用户名获取问题,您可以将它们缓存在组件外部(商店,la redux)之外的某个地方,也可以将其移回父组件并预先解析所有用户名:
const [usernames,setUsernames] = useState({});
const resolveUsernames = useCallback(async authorIds => {
// create an array of 'getUserName' promises and wait for them to all come back
const usernames = await Promise.all(authorIds.map(id => getUserName(id)));
// map the names back to the corresponding ids,e.g. { 123: 'alice',456: 'bob'}
// Promise.all results come back in the same order as the input promises,so you can associate them by index.
const idMap = authorIds.reduce((ids,id,index) => ({
...ids,[id]: usernames[index]
}),{});
// store the id-to-name mapping in state:
setUsernames(idMap);
},[authorIds])
function getMessage() {
axios.get(messApiRest + "/api/messages",{
headers: { 'Authorization': "Bearer " + props.token },params: { 'citycode': props.cityCode },})
.then(response => {
const results = response.data.results;
// this is just a shorthand way of getting an array of distinct ids
const authorIds = [...new Set(results.map(message => message.author.id))];
resolveUsernames(authorIds);
setAllMessages(response.data.results)
})
}
在此位置上,您可以从组件的usernames
状态中查找每条消息的用户名:
{allMessages.map(message => (
<Text>
{usernames[message.author.id]}: {message.content}
</Text>
))
}
,
无限循环是由于在返回的JSX中调用getUserName
。
您可以尝试获取useEffect
中的用户和消息,并仅在两者都被获取时更新状态:
function Chat(props) {
const messApiRest = "https://...";
const [lastMessage,setLastMessage] = useState("");
const [user,setUser] = useState("");
const [categoryMessage,setcategoryMessage] = useState("");
const [idUser,setIdUser] = useState("");
const [allMessages,setAllMessages] = useState([]);
const [messageOneByOne,seMessageOneByOne] = useState([]);
useEffect(() => {
getMessage()
.then((res) => {
return res.data.results;
})
.then((msgs) => {
const userPromises = msgs.map((m) => getUserName(m.author.id));
Promise.all(userPromises).then((users) => {
setAllMessages(
msgs.map((msg,index) => ({ ...msg,user: users[index] }))
);
});
});
},[]);
function getMessage() {
return axios.get(messApiRest + "/api/messages",{
headers: {
Authorization: "Bearer " + props.token,},params: {
citycode: props.cityCode,});
}
function getUserName(toto) {
return axios.get(messApiRest + "/api/users/" + toto,});
}
return (
<View style={styles.container}>
{allMessages.map(function (message) {
return (
<Text>
{message.user}: {message.content}
</Text>
);
})}
</View>
);
}
export default Chat;
在此示例中,我将user
和messages
合并到allMessages
中,但是您可以根据需要进行更改。
谢谢您的回答。我都尝试过,每个都解决了一些问题,但不是全部。
我可能已经更具体了:即使我不得不重新考虑方法的逻辑,我也在寻找更简单的代码。
这就是我想要做的:
1 /使用axios访问API,以获取特定区域中发布的所有消息的数据。这些数据为我提供了消息的内容,我要显示的女巫以及ID。用户。
2 /我想使用该ID。的用户再次调用该API,以便这次获得用户名,并在消息内容之前显示它。
我选择的主要方法: A /我可以将消息内容和用户名都保存在不同的数组中,并并行映射它们以显示数据。 B /我只能调用一个API来获取消息的所有数据,将它们存储在一个数组中,然后映射该数组以显示消息的内容,然后在第二次调用该API时检索该消息的名称。用户的ID。这就是我尝试的解决方案。
是的,我是菜鸟,但是我认为我想做的是基本的,不需要那么多代码行。但是也许我错了^^
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。