Javascript 在渲染之前,真的需要一些帮助来弄清楚componentWillMount()的逻辑吗
这可能是一种长期阅读,我已经阅读和尝试了这么多的解决方案,但没有成功!基本上我有三个MySQL表,一个是用户列表,另一个是文件数据列表。它们与第三个表配对,该表有一列表示用户id,一列表示文件id 当用户登录到应用程序时,它会从表1中获取其ID,转到表3,查找与其用户ID位于同一行的所有文件ID,然后从表2中返回文件信息。基本上是直截了当的,但事实并非如此 我当前的代码:Javascript 在渲染之前,真的需要一些帮助来弄清楚componentWillMount()的逻辑吗,javascript,reactjs,axios,Javascript,Reactjs,Axios,这可能是一种长期阅读,我已经阅读和尝试了这么多的解决方案,但没有成功!基本上我有三个MySQL表,一个是用户列表,另一个是文件数据列表。它们与第三个表配对,该表有一列表示用户id,一列表示文件id 当用户登录到应用程序时,它会从表1中获取其ID,转到表3,查找与其用户ID位于同一行的所有文件ID,然后从表2中返回文件信息。基本上是直截了当的,但事实并非如此 我当前的代码: componentWillMount() { this.getClientFiles(); } 这要求: getC
componentWillMount() {
this.getClientFiles();
}
这要求:
getClientFiles() {
let id = this.props.currentUser.user_id;
let file_refs = [];
axios.get(`/users/get-client-files/${id}`)
.then(res => {
let response = res.data.response;
for (let i = 0; i < response.length; i++) {
file_refs.push(response[i].file_id);
}
this.setState({
file_refs
});
this.getFileData();
});
}
在这里,函数循环遍历处于状态的fileRefs,对每个引用ID进行调用,并将其返回到fileData并将其保存到状态
问题是。。。。在登录后加载第一页时,文件不会呈现。如果你点击cmd+R刷新,它们就在那里。我了解承诺链和JS函数的异步性质,我了解componentWillMount()
应该在安装组件之前运行,并且setState
应该触发组件的重新呈现
我尝试过的事情:
1) 在返回(
)之前的渲染()之后添加以下代码:
当函数在返回的_数据的状态设置为true之前异步运行时,结果是呈现闪烁,其中4-5个呈现
2) 将setState({returned_data:true})
移动到getClientFiles()函数中。这只是提前结束渲染,在刷新页面之前不会生成任何文件
3) 将componentWillMount()
换成componentDidMount()
显然,函数链和React的内置方法中有一个基本方面我没有
有人能帮忙吗
编辑#1
问题似乎是在第一次渲染时,let id=this.props.currentUser.user\u id
是未定义的
,因此getClientFiles
中的调用实际上是要/users/get client files/undefined
编辑#2-由@devserkan请求
我希望这就是你想要的:)
第一批
get client files/${id}
:返回空数组
/get file/“+fileRefs[i]
:不运行
第二次加载:
get client files/${id}
:返回包含5项的数组
/get file/“+fileRefs[i]
:根据每个文件的详细信息适当运行5次
很明显,问题在于,get client files/${id}
没有得到任何东西,因为它没有从中搜索的${id}
。ID是通过道具传递的,但似乎不能立即使用
编辑#3
下面是获取ID并将其设置为state的函数
getUser = () => {
let localToken = localStorage.getItem("iod_tkn");
axios({
url: "/admins/current",
method: "get",
headers: {
Authorization: localToken
}
})
.then(result => {
this.setState({
isLoggedIn: true,
user: result.data,
user_id: result.data.user_id
});
})
.catch(err => {
this.setState({ isLoggedIn: false });
console.log(err);
});
};
和App.js呈现以下内容:
render() {
const { loading } = this.state;
if (loading) {
return <Spinner />;
}
return (
<AdminProvider>
<FileProvider>
<Provider>
<Appbar isLoggedIn={this.state.isLoggedIn} logout={this.logout} />
<Main
getUser={this.getUser}
isLoggedIn={this.state.isLoggedIn}
currentUser={this.state.user}
/>
<BottomNav />
</Provider>
</FileProvider>
</AdminProvider>
);
}
render(){
const{loading}=this.state;
如果(装载){
返回;
}
返回(
);
}
因此,通过将this.state.user
传递到Main.js中,该组件应该在收到道具后重新呈现,对吗 我认为您的代码结构有问题setState
是一个异步函数,它将回调作为第二个参数。你应该利用它的优势。您可以在setState完成后执行函数,并使用第二个参数回调(更新程序函数)使用更新的状态,如:
已编辑第二个选项不应设置statefile_refs
,除非在渲染方法中使用它。
试试这个:
axios.get(`/users/get-client-files/${id}`)
.then(res => {
let response = res.data.response;
for (let i = 0; i < response.length; i++) {
file_refs.push(response[i].file_id);
}
this.getFileData(file_refs);
});
getFileData(file_refs) {
let fileRefs = file_refs;
let fileData = [];
// rest of your code
}
axios.get(`/users/get client files/${id}`)
。然后(res=>{
让响应=res.data.response;
for(设i=0;i
如果问题仍然存在,请告诉我。很乐意提供帮助问题在于,在componentWillMount()
中,异步调用可能无法在呈现装载阶段之前及时检索结果,因此会产生意外的副作用。很可能组件将使用空数据进行渲染。
从异步调用呈现数据的最佳位置是componentDidMount()
作为补充说明,从16.3版开始,componentWillMount()
被认为是生命周期中不安全的方法,在未来的版本中将被删除,因此您最好不要再使用它。因为您的用户id
来自异步作业,所以您应该执行条件渲染。比如:
{ user_id && <ClientDashboard user_id={user_id} ... /> }
{user\u id&&}
另外,你还可以稍微整理一下你的代码:)我在这里模仿你的应用程序
const用户文件=[
{文件id:1,客户端名称:“foo”},
{文件id:2,客户端名称:“bar”},
{文件id:3,客户端名称:“baz”},
];
常量文件=[
{文件id:1,名称:“fizz”,大小:10},
{文件id:2,名称:“buzz”,大小:20},
{文件id:3,名称:“fuzz”,大小:30},
];
const fakeRequest=()=>新承诺(解析=>
setTimeout(()=>解析(用户文件),1000)
);
const fakeRequest2=id=>新承诺(解析=>{
const file=files.find(el=>id==el.file\u id);
setTimeout(()=>解析(文件),1000)
}
);
类应用程序扩展了React.Component{
状态={
文件参考文献:[],
客户端文件:[],
返回的数据:false,
}
componentDidMount(){
此文件为.getClientFiles();
}
getClientFiles(){
伪造
。然后(res=>{
const file_refs=res.map(el=>el.file_id);
这是我的国家({
文件参考
});
这是.getFileData();
});
}
获取文件
this.setState({
file_refs
}, () => {
this.getFileData();
});
axios.get(`/users/get-client-files/${id}`)
.then(res => {
let response = res.data.response;
for (let i = 0; i < response.length; i++) {
file_refs.push(response[i].file_id);
}
this.getFileData(file_refs);
});
getFileData(file_refs) {
let fileRefs = file_refs;
let fileData = [];
// rest of your code
}
{ user_id && <ClientDashboard user_id={user_id} ... /> }