Showing JSON Data using fetch api and map in reactjs [duplicate] - javascript

This question already has answers here:
How can I return multiple lines JSX in another return statement in React?
(8 answers)
Closed 4 years ago.
I have been trying to using fetch api to display json and to use map to iterate the data, but I am stuck in displaying json and iterating it in reactjs
Here is the file
App.js
import React, { Component } from 'react';
import './App.css';
class App extends Component {
constructor(props) {
super();
this.state = {
productlist: [],
error: null,
}
}
componentDidMount(){
fetch(`http://texpertise.in/data.php`)
.then(result => result.json())
.then(productlist => this.setState({productlist: productlist.value}))
}
render() {
return (
<div>
{this.state.productlist.map(product =>
<div> {product.name} </div>
<div> {product.description} </div>
<div> {product.image} </div>
<div> {product.nonVeg} </div>
<div> {product.spicy} </div>
)}
</div>
);
}
}
export default App;
<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>
I am getting this error
./src/App.js
Syntax error: reactspa/src/App.js: Adjacent JSX elements must be wrapped in an enclosing tag (42:23)
40 | {this.state.productlist.map(product =>
41 | <div> {product.name} </div>
> 42 | <div> {product.description} </div>
| ^
43 | <div> {product.image} </div>
44 | <div> {product.nonVeg} </div>
45 | <div> {product.spicy} </div>

When using react 15.1, your .map can only return a single element, in your case, you are returning
<div>{product.name}</div> <div>{product.description}</div>
it should be wrapped and returned as a single element
<div><div>{product.name}</div> <div>{product.description}</div></div>

Related

Syntax error with creating a popup in React

I am trying to create a simple pop up using React. In other words, when a user clicks on a button, a simple pop up should appear. However, with my current implementation I am getting a syntax error and I am unsure why. Any help would be much appreciated!
Here is my main file, where my mock_modal is called, e.g. where my popup is called
import PropTypes from 'prop-types';
import React from 'react';
...
class Calendar extends React.Component {
...
mockModalClick () {
}
hoverCustomSlot() {
this.setState({ hoverCustomSlot: !this.state.hoverCustomSlot });
}
render() {
const description = this.state.hoverCustomSlot ?
(<h4 className="custom-instructions">
Click, drag, and release to create your custom event
</h4>)
: null;
const addMockModal = this.props.registrarSupported ? (
<div className="cal-btn-wrapper">
<button
type="submit"
form="form1"
className="save-timetable add-button"
data-for="sis-btn-tooltip"
data-tip
onClick={this.state.seen ? <MockModal toggle={this.togglePop} /> : null}
>
<img src="/static/img/star.png" alt="SIS" style={{ marginTop: '2px' }} />
</button>
<ReactTooltip
id="sis-btn-tooltip"
class="tooltip"
type="dark"
place="bottom"
effect="solid"
>
<span>See my Mock Modal!</span>
</ReactTooltip>
</div>
) : null;
Here is the definition of my pop up
import React, { Component } from "react";
export default class PopUp extends Component {
handleClick = () => {
this.props.toggle();
};
render() {
return (
<div className="modal">
<div className="modal_content">
<span className="close" onClick={this.handleClick}>
×
</span>
<form>
<h3>Register!</h3>
<label>
Name:
<input type="text" name="name" />
</label>
<br />
<input type="submit" />
</form>
</div>
</div>
);
}
}
I have added ellipses and did not include other unnecessary code. The exact error that I am getting is:
ERROR in ./static/js/redux/ui/modals/mock_modal.jsx
web_1 | Module build failed: SyntaxError: Unexpected token (4:14)
export default class PopUp extends Component {
handleClick = () => {
this.props.toggle();
Try adding a const in front of handleClick.

How to switch classes onClick

thank you for reading this. I am attempting to learn React by making a dummy website, however I've run into a roadblock.
I want the "display-page" div to only show the Send element initially (which is easy) but when someone clicks one of the 4 options from the content_bar div I want remove the current element and only show the newly clicked element (in this case it is 'Transactions')
I've read about useState and routing but I'm not sure how to implement
Thanks! Please let me know if I didnt give enough details
import React, { Component } from 'react';
import './Data.css';
import Transactions from './Transactions';
import Send from './Send';
class Data extends Component {
constructor(props) {
super(props);
this.state = {
content: <Send />
}
}
transactionpage = () => {
this.setState({content: <Transactions/>});
}
render() {
return(
<div className="content">
<div className="content_bar">
<h5>Send</h5>
<h5 onClick={this.transactionpage}>Transactions</h5>
<h5>Friends</h5>
<h5>Professional</h5>
</div>
<div className="display-page">
{this.state.content}
</div>
</div>
);
}
}
export default Data;
Looking at You can't press an <h5> tag and React code without state feels strange.
You need to learn more to achieve your goal, these are the topics:
JSX expresssion
Conditional rendering
State management
Let me show you my solution, it is one of many ways.
class Data extends Component {
constructor(props) {
super(props);
this.state = {
toDisplay: ''
};
this.changeToDisplay = this.changeToDisplay.bind(this);
}
changeToDisplay(e) {
this.setState({ toDisplay: e.target.textContent.toString() });
}
render() {
return (
<div className="content">
<div className="content_bar">
<button onClick={e => changeToDisplay(e)}>Send</button> <br />
<button onClick={e => changeToDisplay(e)}>Transactions</button> <br />
<button>Friends</button> <br />
<button>Professional</button> <br />
</div>
<div className="display-page">
{this.state.toDisplay === 'Send' ? <Send /> : null}
{this.state.toDisplay === 'Transactions' ? <Transactions /> : null}
</div>
</div>
);
}
}

React JS getting started issue

Hi I am stuck with this issue, am just getting started with react js. Its the HOME js component
when button is clicked I want to show some text ( when flag is true) else it should show nothing.
import React from 'react';
export default class Home extends React.Component{
constructor(props)
{
super(props);
this.state = {flag: false}
this.showMe = this.showMe.bind(this);
}
showMe()
{
this.state.flag ? ((<div> show this when flag is true </div>) : null)
}
render()
{
return(
<div>
<h1>Welcome to the Tornadoes Website {this.state.flag}</h1>
<button type="button" onClick={this.showMe}>Click me </button>
</div>);
}
}
Error on console:
16:2: Parsing error: Unexpected token, expected ":"
14 | {
15 | this.state.flag ? ((<div> show this when flag is true</div>) : null)
> 16 | }
| ^
17 |
18 |
19 | render()
You want the showMe handler to only change state.
the return body of showMe should instead be returned in the render function since you are returning JSX/HTML.
showMe() {
this.setState({flag: !this.state.flag})
}
render()
{
return(
<div>
<h1>Welcome to the Tornadoes Website {this.state.flag}</h1>
<button type="button" onClick={this.showMe}>Click me </button>
{this.state.flag ? ((<div> show this when flag is true </div>) : null)}
</div>
);
}

How to fix 'Objects are not valid as a React child'

Codesandbox link.
I'm getting this error when trying to use filter() through a big array of objects (defined as 'filteredCharacters'), and render only those match the id of '6' to the screen (only one does).
I console.log(filteredCharacters), and I can clearly see in console that it works. But for some reason, I'm getting a "Objects are not valid as a React child" error thrown.
The code below is from /components/content.js, in the Codesandbox link above.
import React, { Component } from 'react';
import Intro from '../intro/intro';
class Content extends Component {
render() {
// Grab the 'characters' object from App.js, and assign it to 'this.props'
const { characters } = this.props;
// Filter the chracters and return only whose 'id' belongs to that of '6'
const filteredCharacters = characters.filter(characters => {
if (characters.id === 6) {
return (
<div className="characters" key={characters.id}>
<p>Name: {characters.Name}</p>
<p>ID: {characters.id}</p>
<p>Job: {characters.Job}</p>
<p>Age: {characters.Age}</p>
<p>Weapon: {characters.Weapon}</p>
<p>Height: {characters.Height}</p>
<p>Birthdate: {characters.Birthdate}</p>
<p>Birthplace: {characters.Birthplace}</p>
<p>Bloodtype: {characters.Bloodtype}</p>
<p>Description: {characters.Description}</p>
</div>
)
}
});
// Check to see if it logs properly (it does)
console.log(filteredCharacters);
// When trying to render this to the screen below, it doesn't work
return (
<div>
{filteredCharacters}
</div>
)
}
}
export default Content;
filter will only create a new array with all the elements that returned a truthy value from the function.
You can instead use filter first to get the relevant characters, and then use map on the new array to get the JSX you want to render.
const filteredCharacters = characters
.filter(character => character.id === 6)
.map(character => (
<div className="characters" key={character.id}>
<p>Name: {character.Name}</p>
<p>ID: {character.id}</p>
<p>Job: {character.Job}</p>
<p>Age: {character.Age}</p>
<p>Weapon: {character.Weapon}</p>
<p>Height: {character.Height}</p>
<p>Birthdate: {character.Birthdate}</p>
<p>Birthplace: {character.Birthplace}</p>
<p>Bloodtype: {character.Bloodtype}</p>
<p>Description: {character.Description}</p>
</div>
));
Adding to #Tholle's answer, you could combine those operations into one with reduce
const filteredCharacters = characters
.reduce((acc, character) => {
if (character.id !== 6) return acc;
acc.push(<div className="characters" key={character.id}>
<p>Name: {character.Name}</p>
<p>ID: {character.id}</p>
<p>Job: {character.Job}</p>
<p>Age: {character.Age}</p>
<p>Weapon: {character.Weapon}</p>
<p>Height: {character.Height}</p>
<p>Birthdate: {character.Birthdate}</p>
<p>Birthplace: {character.Birthplace}</p>
<p>Bloodtype: {character.Bloodtype}</p>
<p>Description: {character.Description}</p>
</div>);
return acc;
}, []);
Currently you are using one simple object to behave as a node in the HTML structure of the component you are writing. One of the best practices to use react in such cases is to create and then call this as a react component itself.
Following is your code that now has a separate component that can be called on need:
import React, { Component } from 'react';
import Intro from '../intro/intro';
const FilteredCharcters = characters => {
characters.filter(character => {
if (character.id === 6) {
return (
<div className="characters" key={character.id}>
<p>Name: {character.Name}</p>
<p>ID: {character.id}</p>
<p>Job: {character.Job}</p>
<p>Age: {character.Age}</p>
<p>Weapon: {character.Weapon}</p>
<p>Height: {character.Height}</p>
<p>Birthdate: {character.Birthdate}</p>
<p>Birthplace: {character.Birthplace}</p>
<p>Bloodtype: {character.Bloodtype}</p>
<p>Description: {character.Description}</p>
</div>
)
}
});
class Content extends Component {
render() {
const { characters } = this.props;
return (
<div>
<FilteredCharacters characters={characters} />
</div>
)
}
}
export default Content;

How to render a React component inside of itself

I'm learning React and I'm trying to render the <Comment/> component inside of it self, however I get the following error:
TypeError: Cannot read property 'map' of undefined
Comment._this.getResponses
src/Comment.js:28
25 | );
26 | }
27 | getResponses = () => {
> 28 | return this.props.responses.map(p => {
| ^ 29 | return (
30 | <Comment
31 | author={p.author}
and the code:
import React, { Component } from "react";
class Comment extends Component {
render() {
return (
<div className="comment">
<a className="avatar">
<img src={this.props.avatar} />
</a>
<div className="content">
<a className="author">{this.props.author}</a>
<div className="metadata">
<span className="date">{this.props.timeStamp}</span>
</div>
<div className="text">
<p>{this.props.text}</p>
</div>
<div className="actions">
<a className="reply">Reply</a>
</div>
</div>
<div className="comments">{this.getResponses()}</div>
</div>
);
}
getResponses = () => {
return this.props.responses.map(p => {
return (
<Comment
author={p.author}
avatar={p.avatar}
timeStamp={p.timeStamp}
text={p.text}
/>
);
});
};
}
export default Comment;
Please note that this.props.responses is not undefined, and the problem only occurs while I'm trying to use the Comment component. If I replace the Comment component here:
return this.props.responses.map(p => {
return <Comment
author={p.author}
avatar={p.avatar}
timeStamp={p.timeStamp}
text={p.text}
/>
});
with something like this:
return this.props.responses.map(p => {
return (
<div>
<h1>author={p.author}</h1>
<h1>avatar={p.avatar}</h1>
<h1>timeStamp={p.timeStamp}</h1>
<h1>text={p.text}</h1>
</div>
);
});
the code works.
This is because the rendering of <Comment /> relies on the responses prop being defined.
Currently, when you render Comment components in getResponses(), there is no responses prop assigned to those comments:
<Comment
author={p.author}
avatar={p.avatar}
timeStamp={p.timeStamp}
text={p.text}
/>
This in turn means an error will be thrown when these <Comment /> components are rendered, and they attempt to render "children" of their own (during the call to getResponses()) via the undefined responses prop.
To resolve this, you can check to see that the this.props.responses array is defined before proceeding to map and render <Comment/> components in the getResponses() method, like so:
getResponses = () => {
// Check that responses prop is an array before
// attempting to render child Comment components
if(!Array.isArray(this.props.responses)) {
return null;
}
return this.props.responses.map(p => {
return (
<Comment
author={p.author}
avatar={p.avatar}
timeStamp={p.timeStamp}
text={p.text}
/>
);
});
};

Categories

Resources