0

Hi I'm trying to pass and render input values from AddHamster (child) component to HamsterCard Component (parent). I'm getting the error message: Error: Objects are not valid as a React child (found: object with keys {name, age, render}). If you meant to render a collection of children, use an array instead.

Any clue on how I could solve this?

import React, {useState} from "react";

const AddHamster  = () => {
    const [name, setName] = useState( '')
    const [age, setAge] = useState('')
  
    async function postHamster(){
        const newHamster = {
            name: name,
            age: Number(age),
        }
     
        const response = await fetch('/hamsters ', {method: 'POST',
        headers: {'Content-Type': 'application/json'},
        body: JSON.stringify(newHamster)
        })
        const data = await response.json()
        console.log(data, "this is data id"); 
        console.log(newHamster) 
    }
 
    return   {
        name,
        age, 
        render: (
        <div className="add-hamster">
        <form onSubmit={e => { e.preventDefault(); }}>
        <label>Name</label>

        <input value={name} 
          type="text"
          onChange={(e) =>setName(e.target.value)}
          id="addhamster" /> 
         <label>Age</label>

        <input value={age} 
         type="text"
         onChange={(e) =>setAge(e.target.value)} 
         id="addhamster" />
     </form> 

     <button onClick={e => postHamster()}>Add Hamster</button>
     </div>
        
    )}
          
 }

export default AddHamster;

AddHamster.jsx `

import React, {useState, useEffect} from "react";
import './HamsterCard.css';
import Hamster from  './Hamster';
import AddHamster from './AddHamster.jsx';

const HamsterCard = () => {
    const {render, name, age} = AddHamster();
    const [hamsters, setHamsters] = useState([])
    
    
    useEffect(() => {
        async function get(){
        const response = await fetch('/hamsters', {method: 'GET',})
        //fetchar och tar emot data i reponsens
        const data = await response.json() //Data
        setHamsters(data)
        console.log(data)
     
        } 
       get()    
    }, []  );


    return (
      //pass the id inside of the delete function to which id to delete
        <div className="container"> 
            <div className="hamster-card">
            {hamsters.map((hamster) => (
            <Hamster hamster={hamster} 
            key={hamster.id} {...{name, age}}/>  
            ))
            }
            {render}
            </div>
        </div>    
     
    )
}

export default HamsterCard;

HamsterCard.jsx

import React, {useState} from "react";
const Hamster = (props) => {

   const [hamsterDeleted, setHamsterDeleted] = useState(false)
    async function deleteHamster(id) {
        const response = await fetch(`/hamsters/${id}`, { method: "DELETE" });
        setHamsterDeleted(true)
    
        }
 
         return (
                hamsterDeleted ? null : (  
                    <div>
                <button onClick={() => deleteHamster(props.hamster.id)}>Delete</button>
                <h2>{props.hamster.name}</h2> 
                <p>Ålder:{props.hamster.age}</p> 
                <p>Favorit mat:{props.hamster.favFood}</p> 
                <p>Matcher:{props.hamster.games}</p> 
                <img src={'./img/' + props.hamster.imgName} alt="hamster"/> )
                </div>
              ))
        }
    
       
    

export default Hamster;

import React, {useState} from "react";

const AddHamster  = () => {
    const [name, setName] = useState( '')
    const [age, setAge] = useState('')
  
    async function postHamster(){
        const newHamster = {
            name: name,
            age: Number(age),
        }
     
        const response = await fetch('/hamsters ', {method: 'POST',
        headers: {'Content-Type': 'application/json'},
        body: JSON.stringify(newHamster)
        })
        const data = await response.json()
        console.log(data, "this is data id"); 
        console.log(newHamster) 
    }
 
    return   {
        name,
        age, 
        render: (
        <div className="add-hamster">
        <form onSubmit={e => { e.preventDefault(); }}>
        <label>Name</label>

        <input value={name} 
          type="text"
          onChange={(e) =>setName(e.target.value)}
          id="addhamster" /> 
         <label>Age</label>

        <input value={age} 
         type="text"
         onChange={(e) =>setAge(e.target.value)} 
         id="addhamster" />
     </form> 

     <button onClick={e => postHamster()}>Add Hamster</button>
     </div>
        
    )}
          
 }

export default AddHamster;
<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>
2
  • What exactly are you trying to achieve by placing {render} in the HamsterCard component? 'render' is a function, not the component itself. I think if you remove that line it should work. If you want to display the AddHamster component, simply include that instead of render, i.e. <AddHamster /> Commented Feb 7, 2022 at 11:05
  • Also I wouldn't recommend destructuring local state and render function from another react component, it's problematic as state is not exposed on the component object and render is a function which is invoked by react (not intended to be used this way). Commented Feb 7, 2022 at 11:07

1 Answer 1

1

You are exporting a object from AddHamster component.

Error: Objects are not valid as a React child (found: object with keys {name, age, render})

As your error message says Objects are not valid as React Child, you cannot export object from React component and render is a method used in class components.

If you want to access the child data from parent, lift the name and age state from AddHamster (I have combined both the name and age into a single object) to HamsterCard and invoke the AddHamster as <AddHamster/> inside the return of a function.

AddHamster

const AddHamster = ({onChange,value}) => {
  async function postHamster() {
    const newHamster = {
      name: value.name,
      age: Number(value.age)
    };

    const response = await fetch("/hamsters ", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(newHamster)
    });
    const data = await response.json();
    console.log(data, "this is data id");
    console.log(newHamster);
  }
  return (
    <div className="add-hamster">
      <form
        onSubmit={(e) => {
          e.preventDefault();
        }}
      >
        <label>Name</label>

        <input
          value={value.name}
          type="text"
          name="name"
          onChange={onChange}
          id="addhamster"
        />
        <label>Age</label>

        <input
          value={value.age}
          type="text"
          name="age"
          onChange={onChange}
          id="addhamster"
        />
      </form>

      <button onClick={(e) => postHamster()}>Add Hamster</button>
    </div>
  );
};

HamsterCard

const HamsterCard = () => {
    const [hamsters, setHamsters] = useState([])
    const [value,setValue] = useState({name:'',age:''})
    
    
    useEffect(() => {
        async function get(){
        const response = await fetch('/hamsters', {method: 'GET',})
        //fetchar och tar emot data i reponsens
        const data = await response.json() //Data
        setHamsters(data)
        console.log(data)
     
        } 
       get()    
    }, []  );

    const onChange = (e) => {
      setValue(currValue => ({...currValue,[e.target.name]: e.target.value}))
    }


    return (
      //pass the id inside of the delete function to which id to delete
        <div className="container"> 
            <div className="hamster-card">
            {hamsters.map((hamster) => (
            <Hamster hamster={hamster} 
            key={hamster.id} {...value}/>  
            ))
            }
            <AddHamster onChange={onChange} value={value}/>
            </div>
        </div>    
     
    )
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.