React-Tinder-Cards Looping (Function when No more cards) - reactjs

It is required to make the functionality when there is no more data to show.
Here is the code:
import React from "react";
import { adultPack } from "../../../../static/data/packsData";
import TinderCard from "react-tinder-card";
import GameNavbar from "../../Containers/Game_Navbar";
const gif = "https://media.giphy.com/media/RJ2Eet1AB4IOVERF8N/giphy.gif";
export default class AdultPack extends React.Component {
constructor() {
super();
this.state = {
questions: [],
randomQuestions: [],
isLoading: true,
};
}
componentDidMount() {
const shuffled = adultPack.sort(() => Math.random() - 0.5);
this.setState({
randomQuestions: shuffled,
});
}
render() {
return (
<div className="game">
<GameNavbar />
{this.state.randomQuestions.map(function (item, i) {
return (
<TinderCard className="swipe">
<div className="game__content">
<div className="game__content-game">
<div className="game__content-game-title">
<span>Я никогда не</span>
</div>
<h5>{item}</h5>
</div>
</div>
</TinderCard>
);
})}
<img src={gif} alt="Gif" className="game__gif" />
</div>
);
}
}
So, when the data ends after cards scroll, it is shown only blank page. It is required to loop all the items from the "adultPack"

Related

TypeError: Cannot read properties of undefined (reading 'state')

I tried console.log(this.state.bike). It gave me an array that basically contains everything I need. But when I try to access them I get undefined. How do I access the bikeLocation and bikeDescription? I have added 3 files. BikeServices, ListBikes and ViewBike Components.
import React, { Component } from 'react';
import BikeServices from '../services/BikeServices';
class viewBike extends Component {
constructor(props){
super(props)
this.state = {
bikeId: this.props.match.params.bikeId,
bike: {}
}
}
componentDidMount(){
BikeServices.getBikesById(this.state.bikeId).then( (res) => {
this.setState({bike: res.data});
//console.log(this.state.bike);
console.log(this.state.bike.bikeLocation);
});
}
render() {
return (
<div>
<br></br>
{this.state.bikeId}
<br></br>
{this.state.bike.bikeLocation}
</div>
);
}
}
export default viewBike;
//BikeServices
import axios from 'axios';
const BIKE_URL = `http://localhost:8090/api/v1/bikes`;
class BikeService{
getBikes(){
return axios.get(BIKE_URL);
}
getBikesById(bikeId){
return axios.get(BIKE_URL+ '/' +bikeId);
}
}
export default new BikeService();
//ListBikes component
import React, { Component } from 'react';
import BikeService from '../services/BikeServices'
class ListBikes extends Component {
constructor(props) {
super(props)
this.state = {
bikes : [],
}
this.viewBike = this.viewBike.bind(this);
}
// bikes=[]
componentDidMount(){
BikeService.getBikes().then((res) => {
this.setState({ bikes: res.data});
});
}
viewBike(bikeId){
console.log(this.props)
this.props.history.push(`/bike/${bikeId}`);
}
render() {
return (
<div className='container'>
{
this.state.bikes.map(
bike=>
<div className="card">
<div className="card-header">
<img src="https://c0.wallpaperflare.com/preview/483/210/436/car-green-4x4-jeep.jpg" alt="rover" />
</div>
<div className="card-body">
<span className="tag tag-teal">{bike.bikeStatus}</span>
<h4>
Bike Category: {bike.bikeCategory}
</h4>
<p>
Bike Description: {bike.bikeDescription}
<br></br>
Location:
{bike.location.address}, {bike.location.city}, {bike.location.state}, {bike.location.zip}
</p>
<button style={{marginLeft: "10px"}} onClick={() => this.viewBike(bike.bikeId)} className='btn btn-primary'>View</button>
<button>Rent</button>
</div>
</div>
)
}
</div>
);
}
}
export default ListBikes;
I tried console.log(this.state.bike). It gave me an array that basically contains everything I need. But when I try to access them I get undefined. How do I access the bikeLocation and bikeDescription? I have added 3 files. BikeServices, ListBikes and ViewBike Components.

Why is my method Render Props of the React Component not working?

I have a problem. I'm trying do the method Render Prop but it not is working.
My project is: It has to render some names of ComponentDidMount, and I can get it to do the filter and to filter the names. But I passed the function filter for a component, and do the Render Prop.
I pass it here:
import React from 'react';
import './Body.css';
import { Link } from "react-router-dom";
import axios from 'axios';
import Filter from './Filter';
class Body extends React.Component {
constructor(props) {
super(props);
this.state = {
employee: []
}
}
componentDidMount() {
axios
.get("http://127.0.0.1:3004/employee")
.then(response => this.setState({ employee: response.data }));
}
getName = (filter) => {
const { employee, add } = this.state;
return employee.filter(employee => employee.name.includes(filter)).map(name => (
<div className='item' key={name.id}>
<Link className="link" to={`/user/${name.id}`}>
<div key={name.id}>
<img className="img" alt="imgstatic"
src={`https://picsum.photos/${name.id}`}
/>
</div>
<h1 className="name2"> {name.name} </h1>
</Link>
</div>
));
};
getValueInput = (evt) => {
const inputValue = evt.target.value;
this.setState({ input: inputValue });
}
render() {
return (
<div>
<h4 className="manager"> Hello {this.props.currentManager}, here be all employees available for change. </h4>
<div className="body">
{this.getName()}
</div>
<div className='input'>
<Filter render={this.getName} />
</div>
</div>
)
}
}
export default Body;
And here I get him:
import React from 'react';
class Filter extends React.Component {
constructor() {
super();
this.state = {
input: ''
}
}
getValueInput = (evt) => {
const inputValue = evt.target.value;
this.setState({ input: inputValue });
console.log();
console.log(this.state.input)
}
render() {
return (
<div>
<input placeholder='Search name here' type="text" onChange={this.getValueInput} />
</div>
)
}
}
export default Filter
But something's not working...
Can someone help me?
You are not at all using the render prop being supplied to the Filter component. Also the objective of render prop is to render the data, go using this.getName() inside the render Body Component isn't correct either(for one you are not passing the filter value to the getName). You would use it like
import React from 'react';
import './Body.css';
import { Link } from "react-router-dom";
import axios from 'axios';
import Filter from './Filter';
class Body extends React.Component {
constructor(props) {
super(props);
this.state = {
employee: []
}
}
componentDidMount() {
axios
.get("http://127.0.0.1:3004/employee")
.then(response => this.setState({ employee: response.data }));
}
getName = (filter) => {
const { employee, add } = this.state;
return employee.filter(employee => employee.name.includes(filter)).map(name => (
<div className='item' key={name.id}>
<Link className="link" to={`/user/${name.id}`}>
<div key={name.id}>
<img className="img" alt="imgstatic"
src={`https://picsum.photos/${name.id}`}
/>
</div>
<h1 className="name2"> {name.name} </h1>
</Link>
</div>
));
};
getValueInput = (evt) => {
const inputValue = evt.target.value;
this.setState({ input: inputValue });
}
render() {
return (
<div>
<h4 className="manager"> Hello {this.props.currentManager}, here be all employees available for change. </h4>
<div className='body'>
<Filter render={this.getName} />
</div>
</div>
)
}
}
export default Body;
and Filter as
import React from 'react';
class Filter extends React.Component {
constructor() {
super();
this.state = {
input: ''
}
}
getValueInput = (evt) => {
const inputValue = evt.target.value;
this.setState({ input: inputValue });
console.log();
console.log(this.state.input)
}
render() {
return (
<React.Fragment>
{this.props.render(this.state.input)}
<div className='input'>
<input placeholder='Search name here' type="text" onChange={this.getValueInput} />
</div>
</React.Fragment>
)
}
}
Note React.Fragment is available from v16.2.0 onwards and if you are not using the relevant version replace React.Fragment with <div>

ReactJS error TypeError: Cannot read property 'map' of undefined

I'm attempting to consume a JSON API using fetch; the error mentioned above appears on the following line: **this.state.data.map( (dynamicData,key)=>**
This is my ReactJS code with the error line in bold:
import React, { Component } from 'react';
import './App.css';
class App extends Component {
//constructor
constructor() {
super();
this.state = {
data: [],
}
} //end constructor
componentDidMount(){
return fetch('https://jsonplaceholder.typicode.com/todos')
.then((response)=>response.json())
.then((responseJson)=>
{
this.setState({
data:responseJson.todos
})
console.log(this.state.data)
})
} // end component did mount
render() {
return (
<div>
<h2>Todo:</h2>
<div>
{
**this.state.data.map( (dynamicData,key)=>**
<div>
<span> {dynamicData.userId} </span>
<span> {dynamicData.id} </span>
</div>
)
}
</div>
</div>
);
}
}
export default App;
Could I get some help as to what I'm doing wrong? Thanks in advance
import React, { Component } from "react";
import { render } from "react-dom";
class App extends Component {
state = {
data:[],
url: "https://jsonplaceholder.typicode.com/todos"
};
componentDidMount() {
fetch(this.state.url)
.then(response => response.json())
.then(data => this.setState({ data }));
}
render() {
const { data } = this.state;
data && console.log(data);
return (
<div>
{data &&
data.map(item => <div> Hello User With Id: {item.userId} </div>)}
</div>
);
}
}
render(<App />, document.getElementById("root"));
Your didMount should look like mine also, setState takes a callback so if you wanted to see what the data looked like it would be like this
this.setState({ data }, () => console.log(this.state.data))
In your render it looks like you forgot the parenthesis after the arrow function in map.
render() {
return (
<div>
<h2>Todo:</h2>
<div>
{
this.state.data.map((dynamicData,key)=> (
<div>
<span> {dynamicData.userId} </span>
<span> {dynamicData.id} </span>
</div>
))
}
</div>
</div>
);
}

Pagination gets rendered for all views but it should be rendered only on home page in ReactJS?

I have created 3 components:
content
matchinfo
layout
pagination
Whenever I click on view stats button matchinfo component view is rendered which displays matchinfo of particular match. Whenever I click on view stats button (see screenshot) it also renders pagination component also which should not be rendered how can I fix this.
Component matchinfo is child component of content component.
content.js :
import React, { Component } from 'react';
import Matchinfo from './matchinfo';
import './content.css';
class Content extends Component {
constructor(props){
super(props);
this.state = {
matches:[],
loading:true,
callmatchinfo: false,
matchid:''
};
}
componentDidMount(){
fetch('api/matches')
.then(res => res.json())
.then(res => {
console.log(res)
this.setState({
matches:res,
loading:false
});
})
}
viewstats(matchid){
this.setState({
callmatchinfo: true,
matchid: matchid
});
}
rendermatchinfo(){
return <Matchinfo matchid={this.state.matchid} />
}
renderMatches() {
return this.state.matches.slice(this.props.start, this.props.end).map(match => {
return (
<div className="col-lg-3">
<div id="content">
<p className="match">MATCH {match.id}</p>
<h4>{match.team1}</h4>
<p>VS</p>
<h4>{match.team2}</h4>
<div className="winner">
<h3>WINNER</h3>
<h4>{match.winner}</h4>
</div>
<div className="stats">
<button type="button" onClick= {()=>{this.viewstats(match.id)}} className="btn btn-success">View Stats</button>
</div>
</div>
</div>
);
})
}
render() {
if (this.state.loading) {
return <div>Loading...</div>
}
else if(this.state.callmatchinfo){
return <Matchinfo match_id={this.state.matchid} />
}
return (
<div>
<div className="row">
{this.renderMatches()}
</div>
<div className="row">
{this.state.callmatchinfo ? this.rendermatchinfo() : ''}
</div>
</div>
);
}
}
export default Content;
matchinfo.js :
import React, { Component } from 'react';
class Matchinfo extends Component {
constructor(props){
super(props);
this.state = {
info:[],
loading:true
};
}
componentWillMount(){
fetch(`api/match/${this.props.match_id}`)
.then(res => res.json())
.then(res => {
console.log(res)
this.setState({
info:res,
loading:false
})
})
}
render() {
if (this.state.loading) {
return <div>Loading...</div>
}
const {info} = this.state;
return (
<div>
<p className="match">MATCH {info.id}</p>
<h4>{info.team1}</h4>
<p>VS</p>
<h4>{info.team2}</h4>
<div className="winner">
<h3>WINNER</h3>
<h4>{info.winner}</h4>
</div>
</div>
);
}
}
export default Matchinfo;
pagination.js :
import React, { Component } from 'react';
class Pagination extends Component {
handleClick(val){
this.setState({
end:val*16,
start:end-16
});
const end = val*16;
this.props.onChange(end - 16, end);
}
render() {
return (
<div>
<div className="container">
<ul className="pagination">
<li><a href="#" onClick={this.handleClick.bind(this, 1)}>1</a></li>
<li><a href="#" onClick={this.handleClick.bind(this, 2)}>2</a></li>
<li><a href="#" onClick={this.handleClick.bind(this, 3)}>3</a></li>
<li><a href="#" onClick={this.handleClick.bind(this, 4)}>4</a></li>
<li><a href="#" onClick={this.handleClick.bind(this, 5)}>5</a></li>
</ul>
</div>
</div>
);
}
}
export default Pagination;
layout.js :
import React, { Component } from 'react';
import Pagination from './pagination';
import Content from './content';
class Layout extends Component {
constructor(props){
super(props);
this.state = {
start:0,
end:16
};
}
onChangePagination = (start, end) => {
this.setState({
start,
end
});
};
render() {
const {start, end} = this.state;
return (
<div>
<Content start={start} end={end}/>
<Pagination onChange={this.onChangePagination}/>
</div>
);
}
}
export default Layout;
Screenshots:
Onclick view stats button it still shows pagination:
You should approach toggling pagination the same way you did for showing match information. Hold a variable in this.state for your Layout component and make a method that will control that this.state variable. Pass that method down to your child component. Here is a barebones example:
class Layout extends Component {
constructor(props){
super(props);
this.state = {
showPagination: true
}
}
onChangePagination = () => {
this.setState({showPagination: !this.state.showPagination}) //toggles pagination
};
render() {
return (
<div>
{
this.state.showPagination
?
<Pagination onChangePagination={this.onChangePagination}/>
:
<button onClick={this.onChangePagination}>
show pagination
</button>
}
</div>
)
}
}
class Pagination extends Component {
handleClick() {
this.props.onChangePagination()
}
render() {
return (
<div>
<button onClick={this.handleClick}>
toggle pagination
</button>
</div>
)
}
}

Hiding and showing text in React

I'm having troubles wrapping my head around this. I'm trying to show/hide text inside one of my components, but I'm not able to do it. I get I was clicked! message so I know the function is being passed down. What am I missing?
Do I also need to declare a visibility CSS declaration, maybe that's what I'm missing?
SnippetList.jsx
import React, { Component, PropTypes } from 'react'
import { createContainer } from 'meteor/react-meteor-data';
import Snippet from './snippet'
import { Snippets } from '../../../api/collections/snippets.js'
class SnippetList extends React.Component {
constructor(props) {
super(props);
this.state = { visible: false }
this.toggleVisible = this.toggleVisible.bind(this);
}
toggleVisible() {
this.setState( { visible: !this.state.visible } )
console.log('I was clicked');
}
renderSnippets() {
return this.props.snippets.map( (snippet) => (
<Snippet
key={snippet._id}
title={snippet.title}
content={snippet.content}
onClick={this.toggleVisible}
/>
));
}
render() {
const snippets = Snippets.find({}).fetch({});
return (
snippets.length > 0
?
<ul>{this.renderSnippets()}</ul>
:
<p>No Snippets at this time</p>
)
}
}
SnippetList.propTypes = {
snippets: PropTypes.array.isRequired,
}
export default createContainer(() => {
Meteor.subscribe('snippets');
return {
snippets: Snippets.find({}).fetch()
};
}, SnippetList);
Snippet.jsx
import React, { Component, PropTypes } from 'react'
export default class Snippet extends React.Component {
render() {
const visible = this.props.toggleVisible
return (
<article>
<header>
<h1 className='Snippet-title'>{this.props.title}</h1>
</header>
<div className={visible ? 'show' : 'hidden'} onClick={this.props.onClick}>
<p className='Snippet-content'>{this.props.content}</p>
</div>
</article>
)
}
}
Snippet.propTypes = {
title: PropTypes.string.isRequired,
content: PropTypes.string.isRequired
// toggleVisible: PropTypes.func.isRequired
}
the issue is you aren't passing the hide part as a prop.
in Snippet you do const visible = this.props.toggleVisible but... toggleVisible isn't passed to your Snippet component thus its always undefined
return this.props.snippets.map( (snippet) => (
<Snippet
key={snippet._id}
title={snippet.title}
content={snippet.content}
onClick={this.toggleVisible}
/>
));
add toggleVisible... aka change to this.
return this.props.snippets.map( (snippet) => (
<Snippet
key={snippet._id}
title={snippet.title}
content={snippet.content}
toggleVisible={this.state.visible}
onClick={this.toggleVisible}
/>
));
you should probably also bind your renderSnippets this to the class as well... meaning add this to your constructor this.renderSnippets = this.renderSnippets.bind(this);
Now to talk about your code, why are you rendering a <ul> as the parent of a <article> ? the child of a ul should be a <li> I would refactor your components to be more like this.
class SnippetList extends React.Component {
constructor(props) {
super(props);
this.state = { visible: false };
this.toggleVisible = this.toggleVisible.bind(this);
this.renderSnippets = this.renderSnippets.bind(this);
}
toggleVisible() {
this.setState( { visible: !this.state.visible } )
console.log('I was clicked');
}
renderSnippets() {
return this.props.snippets.map( (snippet) => (
<Snippet
key={snippet._id}
title={snippet.title}
content={snippet.content}
toggleVisible={this.state.visible}
onClick={this.toggleVisible}
/>
));
}
render() {
const snippets = Snippets.find({}).fetch({});
return (
snippets.length > 0
? <ul>{this.renderSnippets()}</ul>
: <p>No Snippets at this time</p>
)
}
}
export default class Snippet extends React.Component {
render() {
const {toggleVisible: visible} = this.props;
return (
<li>
<article>
<header>
<h1 className="Snippet-title">{this.props.title}</h1>
</header>
<div onClick={this.props.onClick}>
<p className={visible ? 'show Snippet-content' : 'hidden Snippet-content'}>{this.props.content}</p>
</div>
</article>
</li>
)
}
}

Resources