Javascript 语义用户界面&x2B;使用未定义的数据处理问题

Javascript 语义用户界面&x2B;使用未定义的数据处理问题,javascript,reactjs,jsx,semantic-ui-react,Javascript,Reactjs,Jsx,Semantic Ui React,我还没有反应过来。我在服务器上有JSON文件,通过Node.JS从中获取数据。我想将此数据的第一部分分配给selectedProfile,但它显示undefined。当我尝试分配它时,会显示无法读取代码JSX部分中未定义的属性'*AnyProp*'',即使我尝试this.state.selectedProfile.general.firstName等 import React from 'react'; import ReactDOM from 'react-dom'; import { Ima

我还没有反应过来。我在服务器上有JSON文件,通过Node.JS从中获取数据。我想将此数据的第一部分分配给
selectedProfile
,但它显示
undefined
。当我尝试分配它时,会显示
无法读取代码JSX部分中未定义的属性'*AnyProp*'',即使我尝试
this.state.selectedProfile.general.firstName

import React from 'react';
import ReactDOM from 'react-dom';
import { Image, Search, Grid, Menu } from 'semantic-ui-react';

class ContentFeed extends React.Component {


constructor() {
    super();
    this.state = {
        'items': [],
        'prevName': '',
        'i': 0,
        'selectedProfile': []
    }
    this.getItems = this.getItems.bind(this);

}

componentWillMount() {
    this.getItems();
}


getItems() {

    var jsonData = [];

    const xhr = new XMLHttpRequest();

    xhr.onload = () => {
        if (xhr.status === 200) {
            jsonData = JSON.parse(xhr.responseText);
            this.setState({'items': jsonData});
            this.setState({'prevName': jsonData[0].general.firstName + ' ' + jsonData[0].general.lastName});
            document.getElementById(this.state.prevName).style = 'border: 3px solid black';
            this.setState({'selectedProfile': this.state.items[0]});
            console.log(jsonData);
        } else {
            console.log('Error: No 200 OK response');
        }
    }

    xhr.open('get', 'http://localhost:8000/api/item');
    xhr.send();

}

handleItemClick = (e, { name }) => {
    if (name !== this.state.prevName) {
        document.getElementById(name).style = 'border: 3px solid black';
        document.getElementById(this.state.prevName).style = 'border: 1px solid black';
        this.setState({'prevName': name});
        let i = this.state.items.findIndex(element => {
            return (element.general.firstName + ' ' + element.general.lastName) === name;
        });
        this.setState({'i': i});

        this.setState({'selectedProfile': this.state.items[i]});
    }
}

render() {
    return (
        <Grid>
            <Grid.Column width={4} style={{'height': '700px', 'overflowY': 'scroll'}}>
                <Search />              
                    {this.state.items.map( (item, index) => {
                    return (
                        <Menu key={index} fluid vertical tabular>
                            <Menu.Item 
                                key={item.general.firstName + ' ' + item.general.lastName}
                                name={item.general.firstName + ' ' + item.general.lastName} 
                                id={item.general.firstName + ' ' + item.general.lastName} 
                                onClick={this.handleItemClick}
                                style={{border: '1px solid black'}}
                            >
                            <Image src={item.general.avatar} style={{'width': '50px', 'height': '50px'}}/>
                            <p><br />{item.general.firstName + ' ' + item.general.lastName}</p>
                            <p>{item.job.title}</p>
                            </Menu.Item>
                        </Menu>
                    )
                })}
            </Grid.Column>

            <Grid.Column stretched width={12}>
              <div style={{'margin': 'auto'}} id="content">
                    <h2 style={{'marginTop': '10px', 'overflow': 'auto'}}>{this.state.selectedProfile[0]} {this.state.selectedProfile[1]}</h2>
                    <p></p>
                    <Image style={{'margin': '10px', 'float': 'left'}} src={this.state.selectedProfile[2]}/>
                    <p>Company: {this.state.selectedProfile[3]}</p>
                    <p>Title: {this.state.selectedProfile[4]}</p><br />
                    <p>Email: {this.state.selectedProfile[5]}</p>
                    <p>Phone: {this.state.selectedProfile[6]}</p>
                    <p>Address: {this.state.selectedProfile[7]}</p>
                    <p>City: {this.state.selectedProfile[8]}</p>
                    <p>ZIP: {this.state.selectedProfile[9]}</p>
                    <p>Country: {this.state.selectedProfile[10]}</p>
              </div>
            </Grid.Column>
        </Grid>
    );
}
}
从“React”导入React;
从“react dom”导入react dom;
从“语义ui react”导入{图像、搜索、网格、菜单};
类ContentFeed扩展了React.Component{
构造函数(){
超级();
此.state={
“项目”:[],
“prevName”:“,
“i”:0,
“selectedProfile”:[]
}
this.getItems=this.getItems.bind(this);
}
组件willmount(){
这是getItems();
}
getItems(){
var jsonData=[];
const xhr=new XMLHttpRequest();
xhr.onload=()=>{
如果(xhr.status==200){
jsonData=JSON.parse(xhr.responseText);
this.setState({'items':jsonData});
this.setState({'prevName':jsonData[0].general.firstName+''+jsonData[0].general.lastName});
document.getElementById(this.state.prevName).style='border:3px纯黑';
this.setState({'selectedProfile':this.state.items[0]});
console.log(jsonData);
}否则{
log('错误:没有200 OK响应');
}
}
xhr.open('get','http://localhost:8000/api/item');
xhr.send();
}
handleItemClick=(e,{name})=>{
if(name!==this.state.prevName){
document.getElementById(name.style='border:3px纯黑';
document.getElementById(this.state.prevName).style='border:1px纯黑';
this.setState({'prevName':name});
设i=this.state.items.findIndex(元素=>{
return(element.general.firstName+“”+element.general.lastName)==name;
});
this.setState({'i':i});
this.setState({'selectedProfile':this.state.items[i]});
}
}
render(){
返回(
{this.state.items.map((项,索引)=>{
返回(

{item.general.firstName+''+item.general.lastName}

{item.job.title}

) })} {this.state.selectedProfile[0]}{this.state.selectedProfile[1]}

公司:{this.state.selectedProfile[3]}

标题:{this.state.selectedProfile[4]}


电子邮件:{this.state.selectedProfile[5]}

电话:{this.state.selectedProfile[6]}

地址:{this.state.selectedProfile[7]}

城市:{this.state.selectedProfile[8]}

ZIP:{this.state.selectedProfile[9]}

国家:{this.state.selectedProfile[10]}

); } }
您不能通过正常分配来扰乱状态。这行不通:

this.state.selectedProfile[0]=jsonData[0].general.firstName


您应该使用
setState

循环浏览数据并相应地更改状态。您似乎遇到了多个问题。在
getItems()
xhr回调中,您正在执行以下操作

jsonData = JSON.parse(xhr.responseText);
this.setState({'items': jsonData});
this.setState({'prevName': jsonData[0].general.firstName + ' ' + jsonData[0].general.lastName});
this.setState({'selectedProfile': this.state.items[0]});
但是
this.setState
是一个异步函数,这意味着在设置状态时,不能假定
this.state
已经更新。为了便于讨论,如果您在您的状态中设置了多个值,请随意将它们组合到一个语句中,如:

this.setState({ 
  items: jsonData, 
  selectedProfile: jsonData[0],
  prevName: jsonData[0].general.firstName + ' ' + jsonData[0].general.lastName
});
然而,这不是这里唯一的问题,而是一个数据流的问题,您似乎有。你应该考虑到在第一次渲染时你还没有数据。因此,要处理这个问题,在尝试渲染其任何属性之前,您应该检查渲染函数内部是否存在
selectedProfile
。因此,在这种情况下,可以如下更改渲染:

render() {
  const { items, selectedProfile } = this.props;
  if (!selectedProfile) {
    // render nothing till the selected profile is there
    return null;
  }
  // the rest of your rendering to return the grid (you can now use items & selectedProfile without the prefix this.state
}
这意味着无需将默认状态设置为空数组(它不再是空数组,因为您现在正在为其分配一个对象,但我猜您在重构以前的注释时忽略了这一点)

代码中的一个重要注意事项是DOM操纵,您不应该通过选择项并对其进行变异的传统方式来进行DOM操纵,事实上,强烈建议让所有渲染都由您自己进行反应。在那里,
classNames
库可以帮助您进行有条件的
className
选择

您当前对
this.handleItemClick的实现也将暂时失去
this
的上下文,您可以选择在构造函数中绑定
handleItemClick
(就像您对
getItems
所做的那样,在不需要的情况下),或者使用事件处理程序的箭头函数

所以,如果所有这些点都改变了,你会得到一个类似的代码(注意,我曾经使用dog api,因为它易于使用,并且有一个我可以编写的公共api)

constdog=({name,content,isSelected,onSelected})=>{
返回onSelected(name)}className={classNames('breed',{'selected':isSelected})}>{name};
};
类DogList扩展了React.Component{
构造函数(){
超级();
此.state={
加载:对,
selectedBreed:空
};
}
组件willmount(){
这个;
}
componentDidUmount(){
这是错误的;
}
选择品种(breedName){
这是塞斯塔
constructor() {
  super();
  this.state = {
    items: [],
    selectedProfile: null
  };
}
    render() {
        return (this.props.ready) ? this.renderPage() : <Loader active>Getting data</Loader>;
    }

    renderPage() {
        //your render code here
    }