Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

ReactJS Hooks – investigation code's 'Objects are not valid as a React child' error and JS interpretation of a variable to an array

So, I have been attempting to read about this error ( Objects are not valid as a React child. If you meant to render a collection of children, use an array instead and here https://www.g2i.co/blog/understanding-the-objects-are-not-valid-as-a-react-child-error-in-react ), and I (think I) understand it’s an issue of passing a ‘complex’ object to react’s child component/passing a JS object to a component. (am I correct?)

I have located where my issue lays in my code, but I cannot really understand why would the variable be interpreted as a complex object in the first place.

The issue occurs when I’m trying to create at TodoApp.js, addToDo() function.
This function is later on transferred to a child component ‘TodoForm.js’, so it could, on handleSubmit, call his father’s function addToDo():

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

In addToDo(), if I edit, where I add a new element, the field txt ‘s value to a string for example, it works.

TodoApp.js (in code’s comments I have pointed out where is exactly the issue)

import React, {useState} from "react";
import TodoList from './TodoList';
import Paper from '@mui/material/Paper';
import List from '@mui/material/List';
import TextField from '@mui/material/TextField';
import ListItem from '@mui/material/ListItem';
import Divider from '@mui/material/Divider';
import ListItemText from '@mui/material/ListItemText';
import { AppBar, Toolbar, Typography } from "@mui/material";
import { fontWeight } from "@mui/system";
import TodoForm from "./TodoForm";


export default function () {
    let tasks = [
        {id: 1, txt: "thisisTask1", completed: true},
        {id: 2, txt: "thisisITask2", completed: false},
        {id: 3, txt: "SO ORIGINAL", completed: false}
    ]

    let [tasksVal, tasksEdit]  = useState(tasks);


    const tasksTxts = tasksVal.map((task) => 
        <><ListItem><ListItemText>{task.txt}</ListItemText></ListItem> <Divider/></>
        )
    
    
    //issue seems to lay here - if I change txt: "texthere" - no errors (but doesn't add the task either) 
    let addToDo = (taskTxt) => { // a function to later on send to TodoForm for when a Submit occures.
        tasksEdit([...tasksVal, {  id: 4, txt: {taskTxt}, completed: false }])
    };

    return(

        <div>
            <Paper style={{padding: 0, margin: 0, height: "100vh", backgroundColor: "whitesmoke"}}>
                <AppBar position='static' style={{height: "64px"}} color="primary">
                    <Toolbar>
                        <Typography style={{letterSpacing: "3px", fontSize: "40px"}}>Todos with Hooks!</Typography>
                    </Toolbar>
                </AppBar>
                <TodoList tasksTxts={tasksTxts}/>
                <TodoForm AddToDo={addToDo}/>
                
            </Paper>
        </div>
    )

}

TodoForm.js

import React from "react";
import useInputStatee from "./hooks/useInputStatee";
import { Paper, TextField } from "@mui/material";

export default function ({AddToDo}) {
    const [inputVal, inputChange, inputReset] = useInputStatee("");
    console.log(inputVal)
    return (
        <div>
        <Paper>
            <form onSubmit={e => {
                AddToDo(inputVal);
                // inputReset();
            }}>
            <TextField value={inputVal} onChange={inputChange}/>
            </form>
                <p>{inputVal}</p>

        </Paper>
        </div>
    )

}

useInputStatee.js

import React, {useState} from "react";
export default function (initVal) {
    let [value, setValue] = useState(initVal);

    let handleChange = (e) => { // when we get from a form ... we get an e.target.value
        setValue(e.target.value);
    }

    let reset = () => { setValue(""); }

    return [value, handleChange, reset];
    
}

TodoList.js

import React from "react";
import Paper from '@mui/material/Paper';
import List from '@mui/material/List';
import TextField from '@mui/material/TextField';
import ListItem from '@mui/material/ListItem';
import ListItemText from '@mui/material/ListItemText';

export default function ({tasksTxts}) {

return(
    <div>
        <Paper>
            <List>
                {tasksTxts}
            </List>
        </Paper>
     </div>
    )
}

Thanks in advance!

>Solution :

The issue is in tasksTxts, it’s rendering an object instead of valid JSX.

const tasksTxts = tasksVal.map((task) => 
  <>
    <ListItem>
      <ListItemText>
        {task.txt} // <-- task.txt is object { taskTxt }
      </ListItemText>
    </ListItem>
    <Divider/>
  </>
);

let addToDo = (taskTxt) => {
  tasksEdit([
    ...tasksVal,
    {
      id: 4,
      txt: { taskTxt }, // <-- caused here
      completed: false
    }
  ])
};

The tasksTxts needs to access into the additional taskTxt property:

const tasksTxts = tasksVal.map((task) => 
  <>
    <ListItem>
      <ListItemText>
        {task.txt.taskTxt}
      </ListItemText>
    </ListItem>
    <Divider/>
  </>
);

Or the task.txt just needs to be the value you want to display:

let addToDo = (taskTxt) => {
  tasksEdit(tasksVal => [
    ...tasksVal,
    { id: 4, txt: taskTxt, completed: false }
  ])
};

Unrelated Suggestion

You will want to also add a valid React key to the mapped tasks.

Example:

const tasksTxts = tasksVal.map((task) => 
  <React.Fragment key={task.id}> // <-- Valid React key
    <ListItem>
      <ListItemText>
        {task.txt}
      </ListItemText>
    </ListItem>
    <Divider/>
  </React.Fragment>
);
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading