I'm new in React and I trying to build a simple list of items clickable to get data and update the DOM, I have a list of links on render()
const listNews = this.state.news.map((item, i) =>
<ListGroupItem key={i} className="font-size-1 text-left">
<a href='#' onClick={() => this.getInfoNews(i)}>{item.title}</a>
</ListGroupItem>
);
the function "getInfoNews(i)" have this piece of code to display the data into DOM
getInfoNews(i){
var content = {
news : this.state.news[i]
}
console.log(content.news)
if(content.news === undefined){
return (
<Card>
<CardBody>
<CardTitle>Card Title</CardTitle>
<CardSubtitle>Card subtitle</CardSubtitle>
<CardText>Some quick example text to build on the card title and card's content.</CardText>
</CardBody>
</Card>
)
}else{
return (
<Card>
<CardBody>
<div className="container">
<img src={content.news.urlToImage} className="w-100" />
<CardTitle>
<div className="bottom-left font-size-2 bg-dark w-50 p-2 text-uppercase text-left">{content.news.title}</div>
</CardTitle>
</div>
<CardSubtitle className="text-right text-dark font-size-1 mr-4">
by {content.news.author ? content.news.author : "Anonymous"} , published at {content.news.publishedAt}
</CardSubtitle>
<CardText className="text-dark font-size-2 mt-4">
{content.news.description} read more
</CardText>
</CardBody>
</Card>
)
}
}
Work perfect on load first time, but dont work once clicked on every link, the data is loaded but the DOM dont update, some one can help me ? thanks!
React re-renders whenever there is an update to either the state or the props.
For example, you can load new data from API, and then do this.setState to update the component state. Then, react will re-render the component automatically.
Related
I am trying to use carousel in my react project to show reviews. I am using bootstrap carousel.
This is the carousel I am using
But I want to use like this
Every click on the button will slide in a item and one item will slide out.
I can do one at a time but not like this.
Here is my Code:
const ShowReviews = () => {
const { data: reviews, isLoading, refetch } = useQuery('reviews', () => fetch('https://.herokuapp.com/reviews',)
.then(res => res.json()))
refetch()
if (isLoading) {
return <Loading></Loading>
}
return (
<div>
<h1 className='text-center fw-bold my-5'>User Reviews ({reviews.length})</h1>
<div className='bg-dark bg-opacity-25 container-fluid'>
<Carousel>
{reviews.map(review => <Carousel.Item> <ReviewCard
key={review._id}
review={review}
></ReviewCard></Carousel.Item>)}
</Carousel>
</div>
</div>
);
};
export default ShowReviews;
Just put three review cards per Carousel.Item instead of one. Carousel.Item is just a wrapper for one carousel "page".
Carousel.Item is already styled in a certain way, that's why you need a container/wrapper right below it. In my example I used Stack with direction="horizontal":
<Carousel.Item style={{ height: 500 }}>
<Stack
direction="horizontal"
className="h-100 justify-content-center align-items-center"
gap={3}
>
<Card>...</Card>
<Card>...</Card>
<Card>...</Card>
</Stack>
</Carousel.Item>
https://codesandbox.io/s/relaxed-poitras-4w774i
I want to add some text after the cards have rendered three times. these cards take value from a local json file using split and map. i also want to change the text every three times the component has rendered.
import React from 'react';
import data from '../data.json';
import { Card,Button } from 'react-bootstrap';
function Med() {
return (
<div>
{data.slice(0,6).map((item)=>{
return (
<div>
<Card style={{ width: '18rem' }}>
<Card.Body>
<Card.Title>{item.Name}</Card.Title>
<Card.Text>
This is the explaination of product card.
</Card.Text>
<Button variant="primary">Add to cart</Button>
</Card.Body>
</Card>
</div>
)
})}
</div>
)
}
export default Med;
This is my current output. but I want it to display some text after chris's card.
{data.slice(0,6).map((item,index)=>{//use the index to conditionally render })}
Edit #1 -
So, after reading your comment maybe this code will give you an idea
{data.slice(0, 6).map((item, index) => {
return (
<div>
{index < 3 ? <h1>First three</h1> : <h1>From Fourth</h1>
</div>
);
})}
Right now all the cards are aligned in a row but my goal is to create a small space between them.
I'm trying to create a fake Skateboarding eCommerce website. I started with the bearings (the part that goes inside the skateboard wheel to help it rotate). I successfully added all the cards to the page but find manipulating margin on the card with "m-1" using bootstrap adds a margin to the right side of the page for some reason and takes away some of the space that should be used up by the card.
enter code here
import React from 'react';
import { Button, Card } from 'react-bootstrap';
import 'bootstrap/dist/css/bootstrap.min.css';
import bearingsData from './Product/bearingsData';
const Bearings = () => {
return (
<div className="main">
<div className="title">
<h1>Bearings</h1>
</div>
<div className="container " >
<div className="row">
{ bearingsData.map(product => {
return (
<Card className="col-xs-12 col-sm-6 col-md-4 col-lg-3 p-4 " key={ product.id }>
<Card.Img src={ product.image }/>
<Card.Body>
<Card.Title>
{ product.brand }
</Card.Title>
<Card.Text>
{ product.name }
</Card.Text>
<Button> Add to Shopping Cart</Button>
</Card.Body>
</Card>
);
})}
</div>
</div>
</div>
)
}
export default Bearings;
Im trying to handle an aray of inputs in react which are viewed by ".map" function.
The problem is I couldn't give the field a specific value. As a result i couldn't handle the input in onChange function.
I have list of card each card will have a Admin description input and two buttons each one will send a different request.
Here A made the function that present the cards. The porplem is with the input
function createrequestcard(prop){
return(
<Card className="text-center" key={prop._id}>
<div class="wrapper">
<div id="requestspart1" class="left">
<Card.Body>
<Card.Title>Admin Description</Card.Title>
<Card.Text>
<textarea
// --> Value of the index in aray
// --> Handle Change of input
/>
</Card.Text>
</Card.Body>
</div>
<div id="requestspart3" class="left">
<Card.Body>
<Card.Title>CREATE</Card.Title>
<Button variant="outline-success" className="AdminRequestButton">APPROVE</Button>
<Button variant="outline-danger" className="AdminRequestButton">DENY</Button>
</Card.Body>
</div>
</div>
</Card>
)
}
In initialising values on class
this.state = {
requests: [],
description: '',
}
}
The request aray is updated from the backend:
componentDidMount(){
this.checkloginstatus();
axios.get('http://localhost:3000/request', {withCredentials: true})
.then(resp => {
this.setState({requests: resp.data})
}).catch(err => console.log(err))
}
And in render function:
<div>
{this.state.requests.map(createrequestcard)}
</div>
Thank you very much for helping me out.
You can pass index in map method like the below,
<div>
{this.state.requests.map((req,index) => createrequestcard(req, inex))}
</div>
function createrequestcard(prop, index){
The structure of map method is like below
map((element) => { ... } )
map((element, index) => { ... } )
map((element, index, array) => { ... } )
your card component should defined as follow, here i have named it RequestCard (just to make more readable),
this component will get handleOnChange as argument , we will pass updated value to it,when onchange event occurs in
textarea.
function RequestCard(props){
return(
<Card className="text-center" key={prop._id}>
<div class="wrapper">
<div id={props.id} class="left">
<Card.Body>
<Card.Title>Admin Description</Card.Title>
<Card.Text>
<textarea
onChange={(e)=>props.handleOnChange(e.target.value)}
// --> Value of the index in aray
// --> Handle Change of input
/>
</Card.Text>
</Card.Body>
</div>
<div id="requestspart3" class="left">
<Card.Body>
<Card.Title>CREATE</Card.Title>
<Button variant="outline-success" className="AdminRequestButton">APPROVE</Button>
<Button variant="outline-danger" className="AdminRequestButton">DENY</Button>
</Card.Body>
</div>
</div>
</Card>
)}
now you should render it as follow
<div>
{this.state.requests.map((request,index)=>{
return <RequestCard id={index} handleOnChange={(updatedValue)=>this.handleOnChange(index,updatedValue)}
})}
finally your handleOnChange of parent component should be like this,
handleOnChange=(index,updatedValue)=>{
let curState=this.state;
curState.requests[index].value=updatedValue;//note that i am not aware what member of request you want to update
//so i assume value is the member of request object,you can change whatever you want
this.setState(curState);
}
{userList.map(v => (
<Card
key={v.user}
onClick={() =>
console.log("object")
}
>
<Card.Header
title={v.user}
thumb={require(`../img/${v[tableName].avatar}.png`)}
extra={<span>{v[tableName][extra]}</span>}
/>
<Card.Body>
{v[tableName].desc.split(/\n/g).map((v, k) => (
<li key={k}>{v}</li>
))}
</Card.Body>
</Card>
))}
Click events are not available on the .map() function in React
Card Component of React material UI does not support onClick props so you should not use it.
Quick Fix would be to enclose it inside a div and add onClick on the div as shown below:
<div onClick=> {() =>
console.log("object")
}>
<Card>
.....
</Card>
</div>
Or You can use some different library from :
https://material-ui.com/api/card-action-area/