Getting this warning "Functions are not valid as a React child" - reactjs

I am trying to render a list of movies from an array object in an html table format. I am getting this warning:
Warning: Functions are not valid as a React child. This may happen if you return a Component instead of from render. Or maybe you meant to call this function rather than return it.
import React from 'react';
import {movies} from '../services/fakeMovieService';
class Movies extends React.Component {
constructor(props) {
super(props);
this.tableFormat = this.tableFormat.bind(this);
}
tableFormat() {
movies.map((movie) => {
return (
<tr>
<td key={movie._id}>{movie.title}</td>
</tr>
);
});
}
render() {
return (
<table className="table">
<thead>
<tr>
<th>Title</th>
<th>Genre</th>
<th>Stock</th>
<th>Rate</th>
</tr>
</thead>
<tbody>
{this.tableFormat()}
</tbody>
</table>
);
}
}
export default Movies;

You forgot to call your function.
<tbody>
{this.tableformatter()}
</tbody>
But even by doing, I don't think the result is going to be what you expect.
To render an array of elements in React you should use the map function as said in the docs.
The following result would be :
<tbody>
{movies.map(movie =>
<tr key={movie.title}>
<td>{movie.title}</td>
</tr>
)}
</tbody>
EDIT:
I made a typo and put movies instead of movie.
The following code should do everything you are looking for using map and inline conditions:
const movies = [
{
title: "Spooky",
genre: 'eziojgf',
stock: 'nope',
rate: 87
},
{
title: "Sharknado",
genre: 'shitty',
stock: 'yes',
},
{
title: "haha yes"
},
{
title: "uhmmmm",
rate: -5
}
]
class Movies extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<table className="table">
<thead>
<tr>
<th>Title</th>
<th>Genre</th>
<th>Stock</th>
<th>Rate</th>
</tr>
</thead>
<tbody>
{movies.map(movie =>
<tr key={movie.title}>
{['title', 'genre', 'stock', 'rate'].map(category => <td key={category}>{movie[category]}</td>)}
</tr>
)}
</tbody>
</table>
);
}
}
ReactDOM.render(<Movies />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.5.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.5.1/umd/react-dom.production.min.js"></script>
<div id='root'>

Please execute function as following:
<tbody>
{this.tableformatter()}
</tbody>

here is the right way how to resolve this with React
function TableFormatter ({title /* , and other props genre, rate etc. *//}) {
return (
<tr>
<td>{title}</td>
{/* you may want to add other td here *//}
</tr>
)
}
function Table({movies}) {
render() {
return (
<table className="table">
<thead>
<tr>
<th>Title</th>
<th>Genre</th>
<th>Stock</th>
<th>Rate</th>
</tr>
</thead>
<tbody>
{movies.map(movie => <TableFormatter key={movie.id} {...movie} />)}
</tbody>
</table>
);
}
}

Related

values.map is not a function n reactjs while passing array in state and mapping the current state

I have passed an array of objects in useState hook as the initial state and i want to iterate over it using map method in other component, i have passed the current state as prop in the other object and have used map method over it but console message still shows values.map is not a function, i know we can only use map method on array i have done that only still the error shows.
created state and passed an array of objects-
const [values, setValues] = useState([
{
name: "Vansh",
age: 22,
email: "vansh#gmail.com",
},
]);
Passed values as props in Home component-
<Home
addFormData={addFormData}
setAddFormData={setAddFormData}
values={values}
setValues={setValues}
/>
Code of my home component-
const Home = ({ values }) => { return (
<div>
<table>
<thead>
<tr>
<th>name</th>
<th>age</th>
<th>email</th>
</tr>
</thead>
<tbody>
{values.map((val, index) => (
<tr>
<td key={val.index}>{val.name}</td>
<td key={val.index}>{val.age}</td>
<td key={val.index}>{val.email}</td>
</tr>
))}
</tbody>
</table>
<Link to="/form">
<button>FORM</button>
</Link>
</div> ); };
Please see the code it's working fine export below your missing export.
const Home = ({ values }) => {
// console.log(values);
return (
<div>
<table>
<thead>
<tr>
<th>name</th>
<th>age</th>
<th>email</th>
</tr>
</thead>
<tbody>
{values.map((val, index) => (
<tr>
<td key={val.index}>{val.name}</td>
<td key={val.index}>{val.age}</td>
<td key={val.index}>{val.email}</td>
</tr>
))}
</tbody>
</table>
</div>
);
};
export default Home;
Please see the code SandBoxLink

how to output axios returned data to screen

I am successfully returning data from my axios call on page load.
constructor(props) {
super(props);
this.state = {
myData: []
}
}
componentDidMount() {
let context= this;
axios.get('http://localhost:3000/returntestvalues',{
})
.then((res) => {
console.log("Res os: ", res.data)
context.setState({
myData: res.data
});
})
console.log("res.data", this.state.myData)
}
As you can see there, I am setting the State to the returned data. Now, I want to output this into a table:
render() {
return (
<body onload="renderData()">
<table id="customers">
<tr>
<th>Name</th>
<th>Email</th>
<th>Message</th>
</tr>
<tr>
{this.state.myData?.length > 0
? this.state.myData.map((data, index) => (
<tr key={index}>
<td>{data.name}</td>
<td>{data.email}</td>
<td>{data.message}</td>
</tr>
))
: "No Data Found"}
</tr>
</table>
</body>
);
}
}
however, I don't know how to do this through react, I've only ever done it through ejs. Can anyone help?
render() {
return (
<body onload="renderData()">
<table id="customers">
<tr>
<th>Name</th>
<th>Email</th>
<th>Message</th>
</tr>
<tr>
{this.state.myData?.length > 0
? this.state.myData.map((data, index) => (
<React.Fragment key={index}>
<td>{data.name}</td>
<td>{data.email}</td>
<td>{data.message}</td>
</React.Fragment>
))
: "No Data Found"}
</tr>
</table>
</body>
);
}
}
Here i am assuming that the keys are name email and message. you can change yours.
You can map your received data like below.
return (
<body onload="renderData()">
<table id="customers">
<tr>
<th>Name</th>
<th>Email</th>
<th>Message</th>
</tr>
{this.state.myData?.length>0 && this.state.myData.map(function(data,index){
return (<tr>
<td>{data.name}</td>
<td>{data.email}</td>
<td>{data.message}</td>
</tr>);
})}
</table>
</body>
);

Show value at the alert msg by selecting cell

Goal:
When you press one of the cell (only for column country) containing the name of a country, a alert message with the name of the country should be displayed.
Problem:
What part am I missing in the source code.
Do not know what syntax code is needed in order to achieve the goal.
Any advice?
Info:
I'm newbie in reacjt.
Stackblitz:
https://stackblitz.com/edit/react-faabjl
import React, { Component } from 'react';
import { render } from 'react-dom';
import Hello from './Hello';
import './style.css';
class App extends Component {
constructor() {
super();
this.state = {
name: 'React'
};
}
sayHello() {
alert('');
}
render() {
return (
<div>
<Hello name={this.state.name} />
<table border="1">
<thead>
<tr>
<th>Company</th>
<th>Contact</th>
<th>Country</th>
</tr>
</thead>
<tbody>
<tr>
<td>Alfreds Futterkiste</td>
<td>Maria Anders</td>
<td onClick={this.sayHello}>Germany</td>
</tr>
<tr>
<td>Centro comercial Moctezuma</td>
<td>Francisco Chang</td>
<td onClick={this.sayHello}>Mexico</td>
</tr>
<tr>
<td>Ernst Handel</td>
<td>Roland Mendel</td>
<td>Austria</td>
</tr>
<tr>
<td>Island Trading</td>
<td>Helen Bennett</td>
<td onClick={this.sayHello}>UK</td>
</tr>
<tr>
<td>Laughing Bacchus Winecellars</td>
<td>Yoshi Tannamuri</td>
<td onClick={this.sayHello}>Canada</td>
</tr>
<tr>
<td>Magazzini Alimentari Riuniti</td>
<td>Giovanni Rovelli</td>
<td onClick={this.sayHello}>Italy</td>
</tr>
</tbody>
</table>
</div>
);
}
}
render(<App />, document.getElementById('root'));
Your sayhello function by default contains the event object. By that you can extract the name of the country needs to be displayed.I have rewritten your code.However for large set of table data you need to use a map function to iterate over the whole array of objects and display the result.
import React, { Component } from 'react';
import { render } from 'react-dom';
import Hello from './Hello';
import './style.css';
class App extends Component {
constructor() {
super();
this.state = {
name: 'React'
};
}
sayHello(e) {
alert(e.target.innerHTML);
}
render() {
return (
<div>
<Hello name={this.state.name} />
<table border="1">
<thead>
<tr>
<th>Company</th>
<th>Contact</th>
<th>Country</th>
</tr>
</thead>
<tbody>
<tr>
<td>Alfreds Futterkiste</td>
<td>Maria Anders</td>
<td onClick={this.sayHello}>Germany</td>
</tr>
<tr>
<td>Centro comercial Moctezuma</td>
<td>Francisco Chang</td>
<td onClick={this.sayHello}>Mexico</td>
</tr>
<tr>
<td>Ernst Handel</td>
<td>Roland Mendel</td>
<td>Austria</td>
</tr>
<tr>
<td>Island Trading</td>
<td>Helen Bennett</td>
<td onClick={this.sayHello}>UK</td>
</tr>
<tr>
<td>Laughing Bacchus Winecellars</td>
<td>Yoshi Tannamuri</td>
<td onClick={this.sayHello}>Canada</td>
</tr>
<tr>
<td>Magazzini Alimentari Riuniti</td>
<td>Giovanni Rovelli</td>
<td onClick={this.sayHello}>Italy</td>
</tr>
</tbody>
</table>
</div>
);
}
}
render(<App />, document.getElementById('root'));
You can use a map function like this.
let array = [{company:'Alfreds Futterkiste',contact:'Maria Anders',Country:'Germany'},{company:'centro',contact:'Franciso',country:'Mexico'}]
Now you can iterate over the array with map function.
array.map(element=>{
return <tr key={element.company}>
<td>{element.company}</td>
<td>{element.contact}</td>
<td onClick={this.sayhello}>{element.country}</td>
</tr>
}
I think this is what you want, for Hello component to work you need to update your state to be able to update its value, and to do so you have to bind your event listener to your class component like this:
this.sayHello = this.sayHello.bind(this);
The following is the full code snippet:
import React, { Component } from 'react';
import { render } from 'react-dom';
import Hello from './Hello';
import './style.css';
class App extends Component {
constructor() {
super();
this.state = {
name: 'React'
};
this.sayHello = this.sayHello.bind(this);
}
sayHello(e) {
this.setState({
name: e.target.textContent
});
alert(e.target.textContent);
}
render() {
return (
<div>
<Hello name={this.state.name} />
<table border="1">
<thead>
<tr>
<th>Company</th>
<th>Contact</th>
<th>Country</th>
</tr>
</thead>
<tbody>
<tr>
<td>Alfreds Futterkiste</td>
<td>Maria Anders</td>
<td onClick={this.sayHello}>Germany</td>
</tr>
<tr>
<td>Centro comercial Moctezuma</td>
<td>Francisco Chang</td>
<td onClick={this.sayHello}>Mexico</td>
</tr>
<tr>
<td>Ernst Handel</td>
<td>Roland Mendel</td>
<td>Austria</td>
</tr>
<tr>
<td>Island Trading</td>
<td>Helen Bennett</td>
<td onClick={this.sayHello}>UK</td>
</tr>
<tr>
<td>Laughing Bacchus Winecellars</td>
<td>Yoshi Tannamuri</td>
<td onClick={this.sayHello}>Canada</td>
</tr>
<tr>
<td>Magazzini Alimentari Riuniti</td>
<td>Giovanni Rovelli</td>
<td onClick={this.sayHello}>Italy</td>
</tr>
</tbody>
</table>
</div>
);
}
}
render(<App />, document.getElementById('root'));
you can just treat sayHello() like a normal event in javascript
https://stackblitz.com/edit/react-3zzcoe?file=index.js

Adjacent Jsx elements must be wrapped in an e

i have a very annoying error when trying to display stuff in react table , i would like to make a table and display all values in rows , but for some reason i am getting this error saying Adjacent jsx elemetns must be wrapped in an enclosing element next to the line where im trying to map over results. Any help is greatly appreciated !! thanks!!!
import React from "react";
import "./index.css";
// could also import the sass if you have a loader at dayz/dayz.scss
import moment from 'moment';
import { tasksRef, timeRef } from './firebase';
const defaultColor = "#000";
class Show extends React.Component {
state = {
Events: [],
loading: true
};
render(){
const { Events, Loading } = this.state;
const orderedcars = Events;
let List;
if (Loading) {
List = <div className="TaskList-empty">Loading...</div>;
} else {
List = (
<div>
<table>
<thead>
<tr>
<th scope="row">Event Name</th>
<th scope="row">Event date</th>
<th scope="row">Event timeRef</th>
</tr>
</thead>
<tbody>
{Events.map(car => (
<tr>
<td>{car.name}</td>
<td>{car.timeRef}</td>
<td>{car.description}</td>
</tr>
</tbody>
</table>
))}
</div>
);
}
return(
<div>
{List}
</div>
);
}
}
export default Show;
the problem is that the closing tbody and table atgs should be outside map function as follows
{Events.map(car => (
<tr key={car.name}>
<td>{car.name}</td>
<td>{car.timeRef}</td>
<td>{car.description}</td>
</tr>
))}
You want to place the closing </tbody> and </table> tags outside of the function given to Events.map.
List = (
<div>
<table>
<thead>
<tr>
<th scope="row">Event Name</th>
<th scope="row">Event date</th>
<th scope="row">Event timeRef</th>
</tr>
</thead>
<tbody>
{Events.map(car => (
<tr>
<td>{car.name}</td>
<td>{car.timeRef}</td>
<td>{car.description}</td>
</tr>
))}
</tbody>
</table>
</div>
);

Trying to use react to trigger different components with the same function

I am trying to make a an accordion using React but and I receive my data from a Json API which I dynamically use to make the table. All that works.
However when I try to make the toggleHidden function, it opens every single view instead of the one I just clicked on. How can I target a specific component when clicking instead of just using this
<Table striped bordered condensed hover>
<thead>
<tr>
<th>Asset #</th>
<th>Description</th>
<th>Person</th>
<th>Username</th>
<th>Room</th>
<th>ID</th>
<th>Patches</th>
<th>Date</th>
<th>Java</th>
<th>AACV</th>
</tr>
</thead>
{this.state.items.map((data, key) => {
return (
<tbody>
<tr
id={data.name}
onClick=`{this.toggleHidden.bind(this)}
>`
<td>{data.name}</td>
<td >{data.height}</td>
<td>{data.mass}</td>
<td>{data.gender}</td>
<td >{data.birth_year}</td>
<td>{data.eye_color}</td>
<td >{data.birth_year}</td>
<td>{data.eye_color}</td>
<td >{data.birth_year}</td>
<td>{data.eye_color}</td>
</tr>
<td
className={data.name}
colSpan="10"
>
{!this.state.isHidden && <Filled/>}
</td>
</tbody>
)
})}
</Table>
toggleHidden (e) {
this.setState({
isHidden: !this.state.isHidden
})
}
I Would suggest you to use the power of components.
Create component for row inside the table, something like this:
export default class Row extends React.Component {
render() {
const { data } = this.props;
<tbody>
<tr
id={data.name}
onClick=`{this.toggleHidden.bind(this)}
>`
<td>{data.name}</td>
<td >{data.height}</td>
<td>{data.mass}</td>
<td>{data.gender}</td>
<td >{data.birth_year}</td>
<td>{data.eye_color}</td>
<td >{data.birth_year}</td>
<td>{data.eye_color}</td>
<td >{data.birth_year}</td>
<td>{data.eye_color}</td>
</tr>
<td
className={data.name}
colSpan="10"
>
{!this.state.isHidden && <Filled/>}
</td>
</tbody>
}
toggleHidden() {
this.setState(state => ({
isHidden: !state.isHidden
}));
}
}
and in your main component do something like this:
<Table striped bordered condensed hover>
<thead>
<tr>
<th>Asset #</th>
<th>Description</th>
<th>Person</th>
<th>Username</th>
<th>Room</th>
<th>ID</th>
<th>Patches</th>
<th>Date</th>
<th>Java</th>
<th>AACV</th>
</tr>
</thead>
{this.state.items.map((data, key) => <Row data={data} />}
</Table>
it's more readable, it's more react style, and it's let each row to handle their own state
(there might be some syntax error, but the concept is working)
Good Luck!
Well you need to make nested state for each key that means
const { Table, Icon } = semanticUIReact;
const ITEMS = [
{
asset: "Asset 1",
description: "Description"
},
{
asset: "Asset 2",
description: "Description2"
}
];
class Example extends React.Component {
constructor(props) {
super(props);
this.state = { items: ITEMS };
this.renderRow = this.renderRow.bind(this);
}
render() {
return (
<Table striped bordered condensed selectable>
<Table.Header>
<Table.Row>
<Table.HeaderCell>Asset</Table.HeaderCell>
<Table.HeaderCell>Description</Table.HeaderCell>
</Table.Row>
</Table.Header>
<Table.Body>{this.state.items.map(this.renderRow)}</Table.Body>
</Table>
);
}
renderRow(data, key) {
return (
<Table.Row onClick={() => this.toggleHidden(key)}>
<Table.Cell>{data.asset}</Table.Cell>
<Table.Cell textAlign="right">
{this.state[key] ? "This is hidden" : data.description}
</Table.Cell>
</Table.Row>
);
}
toggleHidden(key) {
this.setState({
[key]: !this.state[key]
});
}
}
ReactDOM.render(<Example />, document.getElementById("react"));
<link href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.3.1/semantic.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/semantic-ui-react#0.79.1/dist/umd/semantic-ui-react.min.js"></script>
<div id="react"></div>

Resources