ReactJS与MongoDB数据查询问题:变量传递及异步执行顺序
解决ReactJS + MongoDB交互的三个问题
咱们一个个拆解你遇到的问题:
问题b:使用roomID=this.state.selectedRoomID查询失效,但显式赋值正常
先看你代码里的细节:
var roomID = this.state.selectedRoomID; console.log(RoomID); //该值打印正常
这里你定义的变量是小写开头的roomID,但打印的是大写开头的RoomID——这在JS里是两个完全独立的变量!如果控制台真的打印出了正确值,大概率是你代码里实际写的是console.log(roomID)(可能是输入时的笔误)。排除这个笔误后,还有两种常见原因:
- State更新的异步性:如果
selectedRoomID是用户选择后刚通过setState更新的,React的setState是异步批量更新的,立刻访问this.state.selectedRoomID可能拿到的还是旧值。你可以在setState的回调里调用addTodo,或者用componentDidUpdate监听selectedRoomID的变化后再执行查询。 - 类型不匹配:比如
selectedRoomID是字符串类型(比如从下拉框拿到的),但MongoDB里的RoomID是数字类型。显式赋值roomID=1是数字,能匹配;但用selectedRoomID的字符串就匹配不到。你可以把roomID转成数字再查询:{"RoomID": Number(roomID)}。
问题c:先打印"outside..."再打印"inside...",如何确保查询先完成
这是JavaScript异步操作的正常表现——MongoDB的find().asArray()是异步Promise操作,会被放到任务队列里,当前同步代码(也就是外面的console.log("outside"+...))会先执行,等异步操作完成后才会执行then里的代码。
要让依赖查询结果的代码在查询完成后执行,有两种常用方式:
方式1:把代码放到then回调里
所有需要用到this.state.MasterDB的逻辑,都放到then里面:
addTodo(event) { event.preventDefault(); var roomID = this.state.selectedRoomID; console.log(roomID); const { mongodb } = this.props; mongodb.db("attendance") .collection("MasterDB").find({"RoomID": roomID}).asArray() .then(MasterDB => { this.setState({ MasterDB }, () => { console.log("inside"+this.state.MasterDB.length); // 这里放所有需要用到MasterDB的逻辑 console.log("outside"+this.state.MasterDB.length); // 移到这里 }); }); }
方式2:用async/await改写,让代码看起来像同步执行
把addTodo改成异步函数,用await等待Promise完成:
async addTodo(event) { event.preventDefault(); var roomID = this.state.selectedRoomID; console.log(roomID); const { mongodb } = this.props; try { const MasterDB = await mongodb.db("attendance") .collection("MasterDB").find({"RoomID": roomID}).asArray(); this.setState({ MasterDB }, () => { console.log("inside"+this.state.MasterDB.length); console.log("outside"+this.state.MasterDB.length); // 现在会在inside之后打印 }); } catch (err) { // 处理查询出错的情况 console.error("查询失败:", err); } }
另外注意:setState本身也是异步的,如果你在setState之后立刻访问this.state.MasterDB,可能还是旧值。用setState的第二个回调就能确保拿到更新后的state。
补充问题a:第一个console.log打印正常
这个说明你能正确获取到selectedRoomID的值(或者你代码里的变量名确实是对的),但结合问题b,还是要先确认变量名的大小写是否一致,避免低级错误。
内容的提问来源于stack exchange,提问作者Sr New
相关产品推荐
相关产品推荐

