【问题标题】:React : Invariant Violation: Objects are not valid as a React childReact : Invariant Violation: 对象作为 React 子对象无效
【发布时间】:2019-03-13 22:58:16
【问题描述】:

我正在研究 ReactJS 搜索过滤器,目前我在输入匹配输入时遇到问题,应用程序崩溃并给出此错误Objects are not valid as a React child (found: object with keys {id, companyName, account, venueCode, openDate, website, primaryPhone, emailAddress, description, firstName, lastName, active, title, department, officePhone, mobilePhone, tenantId, hidden, deleted, parentId}). If you meant to render a collection of children, use an array instead. 有人请帮我解决这个问题。我是初学者,没有太多知识来解决这个问题。当我输入一些匹配输入时,第一次应用程序成功呈现它给我一个错误。

代码

        class Example extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      Item: 5,
      skip: 0
    }

    this.handleClick = this.handleClick.bind(this);
  }

  urlParams() {
    return `http://localhost:3001/meetups?filter[limit]=${(this.state.Item)}&&filter[skip]=${this.state.skip}`
  }

  handleClick() {
    this.setState({skip: this.state.skip + 1})
  }

  render() {
    return (
      <div>
        <a href={this.urlParams()}>Example link</a>
        <pre>{this.urlParams()}</pre>
        <button onClick={this.handleClick}>Change link</button>
      </div>
    )
  }
}


ReactDOM.render(<Example/>, document.querySelector('div#my-example' ))

【问题讨论】:

    标签: javascript reactjs ecmascript-6


    【解决方案1】:

    当你尝试渲染一个对象而不是 JSX 时会发生这种情况。做出我最有根据的猜测,我认为这条线是问题所在:

    let filtered=this.state.data.filter((item)=>{
          return item.companyName.indexOf(keyword) > -1
        });
    

    Filtered 似乎是一个对象数组,而不是 JSX,所以然后在 render 方法中:

    {this.state.filtered.length === 0 ? dataRender : this.state.filtered}
    

    可能会尝试渲染过滤的对象,而不是 JSX。

    要解决此问题,请尝试添加以下内容:

    const filterRender=this.state.filtered.map((dataItem)=>(
      <Table.Row key={dataItem.id}>
      <Table.Cell>{dataItem.companyName}</Table.Cell>
      <Table.Cell>{dataItem.primaryPhone}</Table.Cell>
      <Table.Cell>{dataItem.emailAddress}</Table.Cell>
      <Table.Cell>{dataItem.venueCode}</Table.Cell>
      <Table.Cell>{dataItem.account}</Table.Cell>
      <Table.Cell>{dataItem.openDate}</Table.Cell>
      <Table.Cell>{dataItem.website}</Table.Cell>
      <Table.Cell>{dataItem.description}</Table.Cell>
    </Table.Row>
    ))
    

    并将其更改为:

    {this.state.filtered.length === 0 ? dataRender : filterRender}
    

    正如@jsdeveloper 在下面指出的那样,创建一个renderRow 方法来处理这个问题是个好主意。

    【讨论】:

    • 我还有一个问题,请问您可以吗?
    • @Jon 你有什么问题?
    • 实际上,我想接受小写或大写或大写的输入。我怎么能做到这一点。?请帮忙
    • @Jon 将搜索查询更改为小写,将要比较的项目更改为小写:let keyword =event.target.value.toLowerCase(); let filtered=this.state.data.filter((item)=&gt;{ return item.companyName.toLowerCase().indexOf(keyword) &gt; -1 });
    • 感谢您的留言。实际上,如果我在搜索框中搜索某些内容并单击下一个按钮,它会在控制台中为我提供数组,现在我对下一个按钮有问题。它不会在下一步更新 UI。
    【解决方案2】:

    我要添加到 sleepace 答案中的唯一内容是您应该创建一个函数来映射到数据项:

    getDataItems(data) {
        return data.map((dataItem)=>(
          <Table.Row key={dataItem.id}>
          <Table.Cell>{dataItem.companyName}</Table.Cell>
          <Table.Cell>{dataItem.primaryPhone}</Table.Cell>
          <Table.Cell>{dataItem.emailAddress}</Table.Cell>
          <Table.Cell>{dataItem.venueCode}</Table.Cell>
          <Table.Cell>{dataItem.account}</Table.Cell>
          <Table.Cell>{dataItem.openDate}</Table.Cell>
          <Table.Cell>{dataItem.website}</Table.Cell>
          <Table.Cell>{dataItem.description}</Table.Cell>
        </Table.Row>
        ))
    }
    render() {
      const filteredItems = getDataItems(this.state.filtered)
      const dataItems = getDataItems(this.state.data)
      ...
    

    【讨论】:

    【解决方案3】:

    你应该添加一个 state 属性来处理组件是否准备好渲染或者你必须渲染一个加载器。

    这将解决如果您的属性 this.state.data 已经被您的 getDataMethod 填充的问题。

    所以你应该尝试添加一个初始状态属性,例如:

    class Organization extends Component {
      constructor(props){
        super(props);
        this.state={
          Item : 5,
          skip:0,
          isReady: false,
          data : [],
          filtered:[]
        }
        this.getData=this.getData.bind(this);
        this.btnClick=this.btnClick.bind(this);
        this.prevButton=this.prevButton.bind(this);
      }
    

    并且您应该在 getData 中处理 isReady 状态,例如:

     getData(){
        const {Item,skip}=this.state;
        axios.get(`http://localhost:8001/parties?filter[limit]=${Item}&&filter[skip]=${skip}`)
        .then(response=>{
          console.log(response.data);
          this.setState({
            isReady: true,
            data:response.data
          })
        })
      }
    
    

    并在您的 render 方法中添加条件:

    render() {
        if( !this.state.isReady ){
          return <div>Loading...</div>
        }
        // return your JSX
        return ....
    }
    

    【讨论】:

    【解决方案4】:

    我无法确定这一点,但我希望 dataRender const 返回一系列没有包含父项的行。正确的做法是创建一个&lt;TableRow /&gt; 组件,该组件在 jsx 的渲染函数中使用 map 函数,如下所示:

    ...
    <Table.Body>
        {this.state.filtered.length === 0 ? 
        this.state.data.map((dataItem)=>(<TableRow key={dataItem.id} item={dataItem}/>)
        : this.state.filtered}
    </Table.Body>
    ...
    

    【讨论】:

    【解决方案5】:

    我遇到了这个问题,这是一个非常简单的解决方案。我有一个对象嵌套在一个对象中,然后我尝试在 JSX 中显示该对象,而不是该对象的属性。此错误显示在该对象设置为状态的行,而不是从 JSX 中的状态调用该对象的位置。

    对象处于状态:

        test: { status: { id: 1, text: "value" } }
    

    JSX(错误)

    <div>{this.state.test.status}</div>
    

    JSX(右)

    <div>{this.state.test.status.text}</div>
    

    【讨论】:

      猜你喜欢
      • 2017-02-09
      • 2022-01-14
      • 2019-08-18
      • 2019-07-20
      • 2019-03-09
      相关资源
      最近更新 更多