Here I added two Classes and want to get data from one class to another class but I am getting errors like this "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, { Component } from 'react';
import DataHtml from "../datahtml";
export default class AllData extends Component {
render(){
return (
<div className="row g-6 g-xl-9">
<DataHtml />
</div>
);
}
}
import React, { Component } from 'react';
class DataHtml extends Component {
constructor(props) {
super(props)
this.state = {
data: [ {"name": "demo","date": "02-02-2022"},{"name": "demo","date": "02-02-2022"}]
}
}
DataHtmlStructure = () => {
this.state.data.map((data) => {
return (
<div className="col-md-6 col-xl-4 test-card">
<div className="card-body p-9 pt-4">
<div className="fs-3 fw-bolder text-dark mb-1">{data.name}</div>
<div className="fs-5 text-gray-600">
<i className="bi bi-calendar-date-fill"></i>{data.date}
</div>
</div>
</div>
);
})
}
render() {
return this.DataHtmlStructure;
}
}
export default DataHtml;
You need to invoke your function in your render method.
render() {
return this.DataHtmlStructure();
}
Related
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.
I had already found a solution by luck so I don't quite understand how it worked even after trying to read stuff online.
I am simply trying to get the array of comments inside the selectedDish prop. The selectedDish's state is populated inside the Main Component's function, and I am trying to access selectedDish's array of comments inside the DishDetail component.
I was able to get the comments by:
{ this.props.selectedDish && this.renderComments(this.props.selectedDish.comments)}
But I am unable to when I just do the following and receive this error "Cannot read property 'comments' of undefined":
{ this.renderComments(this.props.selectedDish.comments)}
Why does this work? Shouldn't this.props.selectedDish.comments be enough as I am able to successfully render the "renderDish(dish)" function?
Main Component
import React, { Component } from 'react';
import { Navbar, NavbarBrand } from 'reactstrap';
import Menu from './MenuComponent';
import Dishdetail from './DishdetailComponent';
import { DISHES } from '../shared/dishes';
class Main extends React.Component {
constructor() {
super();
this.state = {
dishes: DISHES,
selectedDish: null
};
// this.onDishSelect = this.onDishSelect.bind(this);
}
onDishSelect(dishId) {
this.setState({
selectedDish: dishId
});
}
render() {
return (
<div>
<Navbar dark color="primary">
<div className="container">
<NavbarBrand href="/">Ristorante Con Fusion</NavbarBrand>
</div>
</Navbar>
<Menu dishes={this.state.dishes} onClick={(dishId) => this.onDishSelect(dishId)} />
<Dishdetail selectedDish={this.state.dishes.filter((dish) => dish.id === this.state.selectedDish)[0]} />
</div>
);
}
}
export default Main;
DishDetail Component
import React, { Component } from 'react';
import { Card, CardImg, CardText, CardBody, CardTitle } from 'reactstrap';
export default class Dishdetail extends React.Component {
constructor(props) {
super(props);
}
renderDish(dish) {
if (dish != null)
return (
<Card >
<CardImg width="100%" src={dish.image} alt={dish.name} />
<CardBody>
<CardTitle>{dish.name}</CardTitle>
<CardText>{dish.description}</CardText>
</CardBody>
</Card>
);
else
return (
<div></div>
);
}
renderComments(comments) {
let list = (<div></div>);
if (comments != null) {
list = (
<ul className="list-unstyled">
{comments.map(c => {
return (
<li key={c.id}>
<p>{c.comment}</p>
<p>-- {c.author}, {new Intl.DateTimeFormat('en-US', { year: 'numeric', month: 'short', day: '2-digit' }).format(new Date(Date.parse(c.date)))}</p>
</li>
);
})}
</ul>
);
}
return (
<div>
<h4>Comments</h4>
{list}
</div>
);
}
render() {
return (
<div className="row">
<div className="col-12 col-md-5 m-1">
{this.renderDish(this.props.selectedDish)}
</div>
<div className="col-12 col-md-5 m-1">
{/* This works: */}
{ this.props.selectedDish && this.renderComments(this.props.selectedDish.comments)}
{/* This doesn't: */}
{/* { this.renderComments(this.props.selectedDish.comments)} */}
</div>
</div>
);
}
}
When your main component renders for the first time the props are still undefined as DISHES haven't been loaded, reasons for that might be the DISHES are initiated with some external resource.
So when this.props.selectedDish is undefined you can't access it's key because they don't exist. So react throws this error.
{ this.props.selectedDish && this.renderComments(this.props.selectedDish.comments)}
So this ensures this.props.selectedDish exists and then you are accessing it's comments key.
When your component is loaded the first time the selectedDish state value is null. It only gets set later, hence the error.
Changing the below code
constructor() {
super();
this.state = {
dishes: DISHES,
selectedDish: null
};
// this.onDishSelect = this.onDishSelect.bind(this);
}
To
constructor() {
super();
this.state = {
dishes: DISHES,
selectedDish: {}
};
// this.onDishSelect = this.onDishSelect.bind(this);
}
will make it work. However I feel that what you are doing now i.e. null check and then render is a more robust way of doing it.
Just a few pointers , you don't need to have a class based component since you aren't using lifecycle methods etc.
you can use destructuring to reduce typing
let {selectedDish:{comments}} = this.props .
You could solve your problem with a default value for comments ,
`const Dishdetail = ({selectedDishes:{comments}}=[]}) => {}
and conditional rendering in render
<div>
{ comments.length > 0 &&
//map you comments here if you have some
}
</div>`
I'm new to ReactJs, coding and this is my first time posting here! So, I'm trying to build a Todo app in ReactJs. I have four components.
the first compo. is App.js - the parent one
import React, { Component } from 'react';
import TaskTodo from './TaskTodo';
import './App.css';
import TaskDisplayed from "./TaskDisplayed";
class App extends Component {
render() {
return (
<div className="App">
<header className="App-header">
<h1 className="App-title">Hey, i'm the header! </h1>
</header>
<div className="App-intro">
<TaskTodo/>
</div>
<div className="App-right">
<TaskDisplayed/>
</div>
</div>
);
}
}
export default App;
TaskTodo.js - which is the parent of the TodoItems.js
import React, {Component} from 'react';
import TodoItems from './TodoItems';
export default class TaskTodo extends Component{
constructor(props) {
super(props);
this.state = {
items: []
};
this.addItem = this.addItem.bind(this);
};
addItem(e) {
const itemArray = this.state.items;
if (this._inputElement.value !== "") {
itemArray.unshift(
{
text: this._inputElement.value,
key: Date.now()
}
);
this.setState({
items: itemArray
});
this._inputElement.value = "";
}
e.preventDefault();
}
render() {
return (
<div className="todoListMain">
<div className="header">
<form onSubmit={this.addItem}>
<input type="text" ref={(a) => this._inputElement = a}
placeholder="Add a list">
</input>
</form>
</div>
<TodoItems entries={this.state.items}/>
</div>
);
}
}
TodoItems.js - the child of the TaskTodo.js
import React, { Component } from 'react';
class TodoItems extends Component {
constructor(props) {
super(props);
this.createTasks = this.createTasks.bind(this);
}
handleClick = (text) => {
console.log(text);
}
createTasks(item) {
return <li key={item.key}><a onClick={() => this.handleClick(item.key, item.text)} href={'#about'}>#{item.text}</a></li>
}
render() {
const todoEntries = this.props.entries;
const listItems = todoEntries.map(this.createTasks);
return (
<ul className="theList">
{listItems}
</ul>
);
}
};
export default TodoItems;
What I need to do, is how I can pass the handleClick method (a child's of TaskTodo) to an 'external' component - TaskDisplayed.js; or how I can track when the user click to a listed item? Please pardon me for this unprofessional way of asking! But, I truly need to get in track with ReactJS! Thanks!
p.s. The above code I found online, so thanks for that :D!
You should define the onClick event handler in the parent component and pass it to the child as a prop.
See How to pass an event handler to a child component in React
In this case, you would want to define it in the App component since that is the parent of the two components that need to communicate.
I have been facing a problem, I would like to write a div every time a specific button is clicked, but the button is in one component and the menu in which I want the div to be created is in another component as well , and both main components are in one component, is there a way of making this happen? So the structure of it all is something like this:
This is the root component with the smaller components in it:
export class Root extends React.Component {
render() {
return(
<div className="Body">
<div id="SideBar" ><SideMenu/></div>
<MenuCocktails/>
<MenuBeers/>
<MenuVines/>
<MenuLemonades/>
<MenuSoftDrinks/>
<MenuCollection/>
<MenuCharger/>
<div id="BottomMenu"><BottomMenu/></div>
</div>
)
}
}
this is the menu that I wanted to div to be created in:
export class BottomMenu extends React.Component{
constructor() {
super();
this.state = {
shown: ''
};
}
toggleMenu = () => {
this.setState({shown: this.state.shown ? '' : 'visible'});
}
render() {
return(
<div>
<button
id="button"
className={this.state.shown}
onClick={this.toggleMenu}
>
My Cart
</button>
<div id="Header" className={this.state.shown}>
<button id="CheckOutButton">Check Out</button>
</div>
</div>
);
}
}
and this is one of the components with the button:
import React from "react";
import styles from "./MenuCocktails.css";
import plus from "./plus.png";
export class NiğdeGazozu extends React.Component{
render() {
return (
<div id="menu-items-1">
<div id="item-name">NIĞDE GAZOZU</div>
<div id ="price-item">8 TL</div>
<button id="plusbutton"><img src={plus}/></button>
</div>
);
}
}
I am very new to React and the ES6 syntax I have a chat widget that i want to toggle to show and hide as i click the header,and I have already implemented an onClick handler, but in terms of the logic I am having trouble finding a similar implementation online. this is my code:
import React, {Component} from 'react';
import chat from './styles.css';
import {connect} from 'react-redux';
class ChatWidget extends Component {
handleClick(event) {
console.log("Hide or unhide chat body")
}
render() {
return (
<div className={chat.container}>
<div onClick={this.handleClick.bind(this)}
className={chat.header}>
<span className={chat.name}>Idol</span>
</div>
<div className={chat.body}>
This is the Body of the chat
</div>
</div>
);
}
}
function mapStateToProps(state) {
return {
user: state.activeUser
};
}
export default connect(mapStateToProps)(ChatWidget);
It could look like this:
class ChatWidget extends Component {
constructor(props) {
super(props);
this.state = {
showChat: true
};
}
handleClick(event) {
this.setState({
showChat: !this.state.showChat
});
}
render() {
return (
<div className={chat.container}>
<div onClick={this.handleClick.bind(this)}
className={chat.header}>
<span className={chat.name}>Idol</span>
</div>
{this.state.showChat &&
(<div className={chat.body}>
This is the Body of the chat
</div>)
}
</div>
);
}
}
function mapStateToProps(state) {
return {
user: state.activeUser
};
}
export default connect(mapStateToProps)(ChatWidget);
But there are different approaches for conditional rendering.
See documentation here: https://facebook.github.io/react/docs/conditional-rendering.html
Use a state variable that will store the current state, whether to show the body or not. On the basis of that variable render the body of the Chart, that is called conditional rendering.
Check this:
class ChatWidget extends Component {
constructor(){
super();
this.state={isShowBody: true}
}
handleClick(event) {
this.setState({isShowBody: !this.state.isShowBody})
}
render() {
return (
<div className={chat.container}>
<div onClick={this.handleClick.bind(this)} className={chat.header}>
<span className={chat.name}>Idol</span>
</div>
{this.state.isShowBody ?
<div className={chat.body}>
This is the Body of the chat
</div>
: null}
</div>
);
}
}
What you can do is create a css class
.hidden {
display: none;
}
And dynamically toggle that class on your <div class={chat.body}.
So add an id to the div so it's easier to grab.
<div class={chat.body} id='chat-body'>
...
</div>
And inside your handleClick method
handleClick(event) {
let chat = document.getElementById("chat-body");
chat-body.classList.toggle('hidden')
}
Here you have an example, it has comments on the lines so you know what each line is doing.
Consider that adding a hidden class to the component will not unmount it, it will just hide it from the DOM
import React, {Component} from 'react';
import chat from './styles.css';
import {connect} from 'react-redux';
class ChatWidget extends Component {
// You need state to update the view
state = {
show: false
}
toggleBody() {
// You can pass true or false to this function to show or hide the body
this.setState({show: !this.state.show})
}
render() {
{/* Take the show property from the state */}
const {show} = this.state
return (
<div className={chat.container}>
<div onClick={this.toggleBody.bind(this)} className={chat.header}>
<span className={chat.name}>Idol</span>
</div>
{/* Add the class hidden to the body if show is false (you should create the hidden class in CSS) */}
<div className={`${chat.body} ${show ? '' : 'hidden'}`}>
This is the Body of the chat
</div>
</div>
);
}
}
function mapStateToProps(state) {
return {
user: state.activeUser
};
}
export default connect(mapStateToProps)(ChatWidget);