React 错误:对象作为 React 子级无效,如果您打算渲染子级集合,请改用数组

Posted

技术标签:

【中文标题】React 错误:对象作为 React 子级无效,如果您打算渲染子级集合,请改用数组【英文标题】:React Error: Objects are not valid as a React child,If you meant to render a collection of children, use an array instead 【发布时间】:2019-06-14 11:17:54 【问题描述】:

当我使用 React 和 Flux 完成了一个 crud 应用程序时,我对 react 不熟悉,我收到了这个错误,我的代码如下,

用户列表

import React,  Component  from "react";
import $ from "jquery";
import UserStore from "../../stores/UserStore";
import * as UserActions from "../../actions/UserActions";
import AddUser from "./AddUser";

$.DataTable = require("datatables.net");

class UserList extends Component 
  constructor() 
    super();
    this.getUsers = this.getUsers.bind(this);
    this.state = 
      users: UserStore.getAll()
    ;
    this.loadUsers();
  

  componentDidMount() 
    $(document).ready(function() 
      $("#example").DataTable(
        ordering: true
      );
    );
  

  componentWillMount() 
    UserStore.on("change", this.getUsers);
  

  componentWillUnmount() 
    UserStore.removeListener("change", this.getUsers);
  

  getUsers() 
    console.log(" get users called");
    this.setState(
      users: UserStore.getAll()
    );
  

  loadUsers() 
    UserActions.getUsersList();
  

  render() 
    const userlistitem = this.state.users.map((user, index) => (
      <tr key=index>
        <th scope="row">index</th>
        <td>user.name</td>
        <td>user.username</td>
        <td>user.email</td>
        <td>user.dob</td>
        <td>user.address</td>
        <td>user.mobile</td>
        <td>user.branch</td>
      </tr>
    ));
    return (
      <div
        style=
          marginTop: 80,
          marginLeft: 150,
          marginRight: 150
        
      >
        <div className="card text-white bg-info mb-3">
          <div className="card-body">
            <div className="d-flex justify-content-between">
              <h5>User List</h5>
              <div>
                <button
                  style=
                    marginTop: 10
                  
                  type="button"
                  className="btn btn-light "
                  data-toggle="modal"
                  data-target="#exampleModalCenter"
                >
                  Add New User
                </button>
              </div>
            </div>
          </div>
        </div>

        <table id="example" className="table table-bordered  table-striped ">
          <thead className="thead-dark">
            <tr>
              <th scope="col">#</th>
              <th scope="col">Name</th>
              <th scope="col">User Name</th>
              <th scope="col">Email</th>
              <th scope="col">DOB</th>
              <th scope="col">Address</th>
              <th scope="col">Mobile</th>
              <th scope="col">Branch</th>
            </tr>
          </thead>
          <tbody>userlistitem</tbody>
        </table>
        <AddUser />
      </div>
    );
  


export default UserList;

添加用户

import React,  Component  from "react";
import DatePicker from "react-datepicker";
import "react-datepicker/dist/react-datepicker.css";
import "../../css/datepicker.css";
import * as UserActions from "../../actions/UserActions";

class AddUser extends Component 
  constructor(props) 
    super(props);
    this.state = 
      branch: "",
      name: "",
      username: "",
      mobile: "",
      email: "",
      address: "",
      dob: new Date()
    ;
    this.handleInputChange = this.handleInputChange.bind(this);
    this.handledatepickerchange = this.handledatepickerchange.bind(this);
  

  handleInputChange(event) 
    const target = event.target;
    const value = target.value;
    const name = target.name;
    this.setState( [name]: value );
  
  handledatepickerchange(event) 
    this.setState( dob: event );
  

  createUser = () => 
    console.log("this is:", this);
    const user = 
      branch: this.state.branch,
      name: this.state.name,
      username: this.state.username,
      mobile: this.state.mobile,
      email: this.state.email,
      address: this.state.address,
      dob: this.state.dob
    ;
    UserActions.createNewUser(user);
    this.setState(
      branch: "",
      name: "",
      username: "",
      mobile: "",
      email: "",
      address: "",
      dob: new Date()
    );
  ;

  render() 
    return (
      <div
        className="modal fade"
        id="exampleModalCenter"
        tabIndex="-1"
        role="dialog"
        aria-labelledby="exampleModalCenterTitle"
        aria-hidden="true"
      >
        <div className="modal-dialog modal-dialog-centered" role="document">
          <div className="modal-content">
            <div className="modal-header">
              <h5 className="modal-title" id="exampleModalCenterTitle">
                Add New User
              </h5>
              <button
                type="button"
                className="close"
                data-dismiss="modal"
                aria-label="Close"
              >
                <span aria-hidden="true">&times;</span>
              </button>
            </div>
            <div className="modal-body">
              <div className="input-group mb-3">
                <input
                  name="name"
                  type="text"
                  className="form-control"
                  placeholder="Name"
                  aria-label="Name"
                  aria-describedby="button-addon2"
                  value=this.state.name
                  onChange=this.handleInputChange
                />
              </div>
              <div className="input-group mb-3">
                <input
                  name="username"
                  type="text"
                  className="form-control"
                  placeholder="User Name"
                  aria-label="User Name"
                  aria-describedby="button-addon2"
                  value=this.state.username
                  onChange=this.handleInputChange
                />
              </div>
              <div className="input-group mb-3">
                <input
                  name="email"
                  type="email"
                  className="form-control"
                  placeholder="Email"
                  aria-label="Email"
                  aria-describedby="button-addon2"
                  value=this.state.email
                  onChange=this.handleInputChange
                />
              </div>
              <div className="input-group mb-3">
                <input
                  name="address"
                  type="text"
                  className="form-control"
                  placeholder="Address"
                  aria-label="Address"
                  aria-describedby="button-addon2"
                  value=this.state.address
                  onChange=this.handleInputChange
                />
              </div>
              <div className="input-group mb-3">
                <input
                  name="branch"
                  type="text"
                  className="form-control"
                  placeholder="Branch"
                  aria-label="Branch"
                  aria-describedby="button-addon2"
                  value=this.state.branch
                  onChange=this.handleInputChange
                />
              </div>
              <div className="input-group mb-3">
                <DatePicker
                  name="dob"
                  type="text"
                  className="form-control"
                  placeholder="DOB"
                  aria-label="DOB"
                  aria-describedby="button-addon2"
                  selected=this.state.dob
                  onChange=this.handledatepickerchange
                />
                <p
                  style=
                    marginTop: "5px",
                    fontWeight: "200",
                    marginLeft: "10px"
                  
                >
                  Date of Birth(dd/mm/yyyy)
                </p>
              </div>
              <div className="input-group mb-3">
                <input
                  name="mobile"
                  type="number"
                  className="form-control"
                  placeholder="Mobile No."
                  aria-label="Mobile No."
                  aria-describedby="button-addon2"
                  value=this.state.mobile
                  onChange=this.handleInputChange
                />
              </div>
            </div>

            <div className="modal-footer">
              <br />
              <br />
              <button
                type="button"
                className="btn btn-secondary"
                data-dismiss="modal"
              >
                Close
              </button>
              <button
                type="button"
                className="btn btn-primary"
                data-dismiss="modal"
                onClick=this.createUser
              >
                Save
              </button>
            </div>
          </div>
        </div>
      </div>
    );
  


export default AddUser;

动作

import dispatcher from "../dispatcher/dispatcher";
import  BASE_URL  from "../utils/AppConstants";

export function getUsersList() 
  console.log("getting the data! ");
  fetch(BASE_URL + "/users")
    .then(res => res.json())
    .then(
      result => 
        console.log("res " + result);
        dispatcher.dispatch( type: "RECEIVE_USERS", users: result );
      ,
      // Note: it's important to handle errors here instead of a catch() block so that
      // we don't swallow exceptions from actual bugs in components.
      error => 
        //  here manage error and close loading;
        console.log("getting error " + error);
      
    );


export function createNewUser(user) 
  console.log("post the data!");
  fetch(BASE_URL + "/saveuser", 
    method: "POST",
    headers: 
      Accept: "application/json",
      "Content-Type": "application/json"
    ,
    body: JSON.stringify(user)
  )
    .then(res => res.json())
    .then(
      result => 
        dispatcher.dispatch( type: "CREATE_USER", newUser: user );
      ,
      // Note: it's important to handle errors here instead of a catch() block so that
      // we don't swallow exceptions from actual bugs in components.
      error => 
        //  here manage error and close loading;
        console.log("getting error " + error);
      
    );

商店

import  EventEmitter  from "events";
import dispatcher from "../dispatcher/dispatcher";

class UserStore extends EventEmitter 
  constructor() 
    super();
    dispatcher.register(this.handleActions.bind(this));
    this.users = [
      
        branch: "19",
        name: "Javcbvcsim11",
        username: "zxcv",
        mobile: "5645654",
        email: "demo@gmail.com111",
        address: "Demo vcbvcbAddress1",
        dob: "2020-11-06T00:00:00.000+0000"
      
    ];
  

  createUser(newUser) 
    this.users.push(newUser);
    console.log("new  users lenght " + this.users.lenght);
    this.emit("change");
  

  getAll() 
    return this.users;
  
  handleActions(action) 
    switch (action.type) 
      case "RECEIVE_USERS": 
        this.users = action.users;
        this.emit("change");
        break;
      
      case "CREATE_USER": 
        this.createUser(action.newUser);
        break;
      
    
  


export default new UserStore();

我不知道这里发生了什么问题。当检查堆栈溢出时,我知道这是迭代数据的问题。但我已经这样做了。即使错误仍然存​​在。如果有人可以提供帮助,那将是非常可观的。 setState 方法中抛出的错误。我在这里使用通量作为架构。当我尝试将新用户添加到我的数据时会出现问题。实际上,当我将它添加到数据库时没有任何问题。问题是当我单击 AddUser 组件中的保存按钮时,它会保存到我的数据库中,但是在它需要再次显示为表格列表但抛出错误之后。

【问题讨论】:

【参考方案1】:

我可以看到的一个问题是您在 JSX 元素 (&lt;td&gt;user.dob&lt;/td&gt;) 中直接使用了user.dobdob 要么是new Date(),要么是react-datepickeronChange 事件的直接输出,两者都是对象。

这是一个试图渲染new Date() 的虚拟组件。

const App = ( text ) => <p>text</p>;

// Passing Date object.
ReactDOM.render(<App text=new Date() />, document.getElementById("app"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

<div id="app"></div>

这对我来说会导致类似this 的错误:

对象作为 React 子级无效(发现时间:2019 年 1 月 21 日星期一 12:37:56 GMT+0530(印度标准时间))。

这意味着你将一个对象,而不是一个字符串作为子元素传递给 JSX 元素。

注意这是如何工作的:

const App = ( text ) => <p>text</p>;

// Passing stringified Date object.
ReactDOM.render(<App text=new Date().toString() />, document.getElementById("app"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

<div id="app"></div>
我将一个字符串作为p JSX 元素的子元素传递。您需要做类似的事情并确保没有对象通过。

实际上,由于您没有发布整个错误,因此很难说是哪个条目导致了错误。但是,user.dob 是我的最佳猜测。

【讨论】:

谢谢老兄。这就是问题【参考方案2】:

在 React 中迭代对象是很棘手的。通常你想使用Object.entries/Object.values/Object.keys 然后.map。这将获取对象并创建一个数组,然后您可以使用.map 遍历该对象。 .map 对对象不起作用,因为它是一个数组函数,所以你必须先把你的对象变成一个数组。 .map 函数将允许您在 React 中进行迭代而不会出现该错误:

 this.state = 
          branch: "",
          name: "",
          username: "",
          mobile: "",
          email: "",
          address: ""
    

    // Not in your constructor 
    let myObj = this.state;

    Object.entries(myObj).map(item => 
       // Successfully iterates, do what you need to do in here
    )

另外,将 JQuery 与 React 结合使用是一个非常糟糕的主意。 React 使用虚拟 DOM,不能很好地与 JQuery 配合使用。

【讨论】:

以上是关于React 错误:对象作为 React 子级无效,如果您打算渲染子级集合,请改用数组的主要内容,如果未能解决你的问题,请参考以下文章

错误:对象无效作为React子级(Axios和openweathermap API)

Apollo 客户端错误,对象作为 React 子级无效(发现:[object Promise])

对象作为 React 子级无效。如果您打算渲染一组孩子,请改用数组 - FlatList

对象作为 React 子级无效如果您要渲染子级集合,请改用数组

尝试基于 AsyncStorage React-Native 渲染组件时,对象作为反应子级无效

错误:对象作为 React 子项无效(找到:带有键 的对象)。改用数组