Javascript Can';使用解析服务器返回的数据更新状态后,无法让React组件重新呈现
我无法使用状态中的数据渲染组件。我从解析服务器中提取数据,然后用这些数据更新状态。但是,使用数据的组件(Javascript Can';使用解析服务器返回的数据更新状态后,无法让React组件重新呈现,javascript,reactjs,parse-server,Javascript,Reactjs,Parse Server,我无法使用状态中的数据渲染组件。我从解析服务器中提取数据,然后用这些数据更新状态。但是,使用数据的组件(在下面的代码中)是在数据可用之前进行渲染的 我尝试了这里描述的方法: 但我无法让组件识别正在更新然后重新呈现的状态 有什么想法吗?代码如下所示。还附上一个屏幕截图,显示成功的控制台日志和状态中存在的数据 (需要注意的是,我是一个新手,所以很多代码可能都不是最优的。) 从“React”导入React; 从“Parse”导入Parse; 从“/MenuItem”导入菜单项; 类MenuItems
在下面的代码中)是在数据可用之前进行渲染的
我尝试了这里描述的方法:
但我无法让组件识别正在更新然后重新呈现的状态
有什么想法吗?代码如下所示。还附上一个屏幕截图,显示成功的控制台日志和状态中存在的数据
(需要注意的是,我是一个新手,所以很多代码可能都不是最优的。)
从“React”导入React;
从“Parse”导入Parse;
从“/MenuItem”导入菜单项;
类MenuItems扩展了React.Component{
构造函数(){
超级();
this.loadMenuItems=this.loadMenuItems.bind(this);
此.state={
菜单项:{},
顺序:{}
};
}
loadMenuItems(){
/*0a.是否获取状态的副本*/
const menuItems={…this.state.menuItems};
/*0.获取用户*/
//TODO:从道具上得到这个
var user=Parse.user.current();
/*1.获取此用户的菜单项*/
var MenuItemTest=Parse.Object.extend('MenuItemTest');
var query=newparse.query(MenuItemTest);
query.equalTo(“用户”,用户);
查询.查找({
成功:函数(返回的菜单项){
log(“成功检索”+returnedMenuItems.length+“菜单项”);
对于(var i=0;i)
}
)
}
}
导出默认菜单项;
更新代码以与注释线程一致
import React from "react";
import Parse from 'parse';
import MenuItem from './MenuItem';
class MenuItems extends React.Component {
constructor() {
super();
this.loadMenuItems = this.loadMenuItems.bind(this);
}
loadMenuItems() {
const menuItems = {};
/* 0. Get User */
var user = Parse.User.current();
/* 1. Get Menu Items for this user */
var MenuItemTest = Parse.Object.extend('MenuItemTest');
var query = new Parse.Query(MenuItemTest);
query.equalTo('user', user);
query.find({
success: function(returnedMenuItems) {
console.log("Successfully retrieved " + returnedMenuItems.length + " menu items.");
for (var i = 0; i < returnedMenuItems.length; i++) {
var object = returnedMenuItems[i];
const menuItem = {
name: object.get('name'),
price: object.get('price'),
label: object.get('label'),
shorthand: object.get('shorthand'),
description: object.get('description')
}
menuItems[`menu-item-${object.id}`] = menuItem;
}
},
error: function(error) {
console.log("Error: " + error.code + " " + error.message);
}
});
this.setState({ menuItems });
}
componentWillReceiveProps(nextProps) {
console.log('I ran');
console.log(nextProps);
this.loadMenuItems();
}
componentWillMount() {
this.loadMenuItems();
}
render() {
// Handle case where the response is not here yet
if (!this.state.menuItems) {
console.log('No state');
return <div>Loading...</div>;
}
// Gives you the opportunity to handle the case where the ajax request
// completed but the result array is empty
if (this.state.menuItems.length === 0) {
console.log('Zero items');
return <div>No menu items yet</div>;
}
if (this.state.menuItems) {
return (
<div className="menu-items">
{ console.log(this.state.menuItems) }
{ console.log(Object.keys(this.state.menuItems)) }
</div>
)
}
}
}
export default MenuItems;
从“React”导入React;
从“Parse”导入Parse;
从“/MenuItem”导入菜单项;
类MenuItems扩展了React.Component{
构造函数(){
超级();
this.loadMenuItems=this.loadMenuItems.bind(this);
}
loadMenuItems(){
常量menuItems={};
/*0.获取用户*/
var user=Parse.user.current();
/*1.获取此用户的菜单项*/
var MenuItemTest=Parse.Object.extend('MenuItemTest');
var query=newparse.query(MenuItemTest);
query.equalTo(“用户”,用户);
查询.查找({
成功:函数(返回的菜单项){
log(“成功检索”+returnedMenuItems.length+“菜单项”);
对于(var i=0;i
据我所知,从你在这里得到的信息
if (!this.state.response) {
return <div>Loading...</div>;
}
if (this.state.response.length === 0) {
return <div>No menu items yet</div>;
}
而您的
构造函数
根本没有将菜单项
设置为状态(因此加载会首先显示)。我找到了解决方案。虽然在试图解决我的问题时,我移动了一些代码来设置父组件的状态,并将其作为道具传递给MenuItems。但它为什么不起作用仍然是一样的
它与loadMenuItems()
有关:
我相信这些组件从未更新过,因为尽管状态是通过menuItems[
菜单项-${object.id}]=menuItem设置的
loopthis.setState()
从未被再次调用,这就是触发组件刷新的原因。我本可以离开这里,但我想这就是发生的事情
我在下面发布了更新的代码以供将来参考
父组件:
import React from "react";
import Parse from 'parse';
import MenuItems from './MenuItems';
class ManageMenu extends React.Component {
constructor() {
super();
this.loadMenuItems = this.loadMenuItems.bind(this);
}
loadMenuItems() {
const menuItems = {};
/* 0. Get User */
var user = Parse.User.current();
/* 1. Get Menu Items for this user */
var MenuItemTest = Parse.Object.extend('MenuItemTest');
var query = new Parse.Query(MenuItemTest);
query.equalTo('user', user);
query.find({
success: function(returnedMenuItems) {
console.log("Successfully retrieved " + returnedMenuItems.length + " menu items.");
for (var i = 0; i < returnedMenuItems.length; i++) {
var object = returnedMenuItems[i];
const menuItem = {
name: object.get('name'),
price: object.get('price'),
label: object.get('label'),
shorthand: object.get('shorthand'),
description: object.get('description')
}
menuItems[`menu-item-${object.id}`] = menuItem;
}
this.setState({ menuItems });
}.bind(this),
error: function(error) {
console.log("Error: " + error.code + " " + error.message);
}
});
}
componentWillMount() {
this.loadMenuItems();
}
render() {
// Handle case where the response is not here yet
// console.log(this.state);
if (!this.state) {
console.log('No state');
// Note that you can return false it you want nothing to be put in the dom
// This is also your chance to render a spinner or something...
return <div>Loading...</div>;
}
if (this.state.menuItems) {
return (
<div className="manage-menu">
<div className="mt3 border-top">
<h3 className="mt1 bold s2">Menu Items</h3>
<div className="mt1">
<MenuItems menuItems={this.state.menuItems} />
</div>
</div>
</div>
)
}
}
}
export default ManageMenu;
import React from "react";
import MenuItem from './MenuItem';
class MenuItems extends React.Component {
render() {
// Same as: const menuItems = this.props.menuItems;
const { menuItems } = this.props;
// No menu items yet
if (menuItems.length === 0) {
console.log('Zero items');
return <div>No menu items yet</div>;
}
if (menuItems) {
return (
<div className="menu-items">
{
Object
.keys(menuItems)
.map(key => <MenuItem key={key} details={menuItems[key]} />)
}
</div>
)
}
}
}
export default MenuItems;
从“React”导入React;
从“Parse”导入Parse;
从“/MenuItems”导入菜单项;
类ManageMenu扩展了React.Component{
构造函数(){
超级();
this.loadMenuItems=this.loadMenuIt
loadMenuItems() {
const menuItems = {};
/* 0. Get User */
var user = Parse.User.current();
/* 1. Get Menu Items for this user */
var MenuItemTest = Parse.Object.extend('MenuItemTest');
var query = new Parse.Query(MenuItemTest);
query.equalTo('user', user);
query.find({
success: function(returnedMenuItems) {
console.log("Successfully retrieved " + returnedMenuItems.length + " menu items.");
for (var i = 0; i < returnedMenuItems.length; i++) {
var object = returnedMenuItems[i];
const menuItem = {
name: object.get('name'),
price: object.get('price'),
label: object.get('label'),
shorthand: object.get('shorthand'),
description: object.get('description')
}
menuItems[`menu-item-${object.id}`] = menuItem;
}
},
error: function(error) {
console.log("Error: " + error.code + " " + error.message);
}
});
this.setState({ menuItems });
}
success: function(returnedMenuItems) {
...
}.bind(this),
import React from "react";
import Parse from 'parse';
import MenuItems from './MenuItems';
class ManageMenu extends React.Component {
constructor() {
super();
this.loadMenuItems = this.loadMenuItems.bind(this);
}
loadMenuItems() {
const menuItems = {};
/* 0. Get User */
var user = Parse.User.current();
/* 1. Get Menu Items for this user */
var MenuItemTest = Parse.Object.extend('MenuItemTest');
var query = new Parse.Query(MenuItemTest);
query.equalTo('user', user);
query.find({
success: function(returnedMenuItems) {
console.log("Successfully retrieved " + returnedMenuItems.length + " menu items.");
for (var i = 0; i < returnedMenuItems.length; i++) {
var object = returnedMenuItems[i];
const menuItem = {
name: object.get('name'),
price: object.get('price'),
label: object.get('label'),
shorthand: object.get('shorthand'),
description: object.get('description')
}
menuItems[`menu-item-${object.id}`] = menuItem;
}
this.setState({ menuItems });
}.bind(this),
error: function(error) {
console.log("Error: " + error.code + " " + error.message);
}
});
}
componentWillMount() {
this.loadMenuItems();
}
render() {
// Handle case where the response is not here yet
// console.log(this.state);
if (!this.state) {
console.log('No state');
// Note that you can return false it you want nothing to be put in the dom
// This is also your chance to render a spinner or something...
return <div>Loading...</div>;
}
if (this.state.menuItems) {
return (
<div className="manage-menu">
<div className="mt3 border-top">
<h3 className="mt1 bold s2">Menu Items</h3>
<div className="mt1">
<MenuItems menuItems={this.state.menuItems} />
</div>
</div>
</div>
)
}
}
}
export default ManageMenu;
import React from "react";
import MenuItem from './MenuItem';
class MenuItems extends React.Component {
render() {
// Same as: const menuItems = this.props.menuItems;
const { menuItems } = this.props;
// No menu items yet
if (menuItems.length === 0) {
console.log('Zero items');
return <div>No menu items yet</div>;
}
if (menuItems) {
return (
<div className="menu-items">
{
Object
.keys(menuItems)
.map(key => <MenuItem key={key} details={menuItems[key]} />)
}
</div>
)
}
}
}
export default MenuItems;