Passing props a on button click - node.js

<Slider {...settings}>
{this.state.featuredMovies.map(movie =>
<div className="" key={movie._id}>
<Card inverse style={{padding: "10px", width: "90%"}}>
<CardImg src={`/files/${movie.thumbnail}`} alt="Card image cap" />
<CardImgOverlay className="movie-list-overlay">
<CardTitle>{movie.MovieName}</CardTitle>
<CardText>{movie.Description}</CardText>
<CardText>
<small>
<a href="watch">
<Button className="btn-fill btn-movie " color="primary" onClick={movie}>
Watch
</Button></a></small>
</CardText>
</CardImgOverlay>
</Card>
</div>
)}
</Slider>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
i want to pass the movie props on button click to the watch component so the watch component
class WatchMovies extends React.Component {
ComponentDidMount(){
const { player } = this.refs.player.getState();
}
handleDelete = e => {
console.log(this.refs.player.play())
}
handleD = e => {
const {player} = this.refs.player.getState()
console.log(player.currentTime)
console.log(this)
}
render() {
return (
<>
<div className="container-fluid bg-black">
<div className="col-md-12 mx-auto pt-5">
<Row className="" >
<div className="col-md-12 mx-auto py-5">
<Player
ref="player"
width="80%"
playsInline
poster="/assets/bg5.jpg"
src="https://media.w3.org/2010/05/sintel/trailer_hd.mp4"
position="center"
LoadingSpinner
onEnded={() => console.log("ended")}
/>
<Button onClick={this.handleDelete}>D </Button>
<Button onClick={this.handleD}>D </Button>
</div>
</Row>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
i want to pass the movie props on button click to the watch component so the watch component. Watch component is where you will be redirect to watch the movie you selected from the movielist component above

Your onClick needs to be a function
<Button onClick={() => this.doSomething(movie)} />
Then you can access the movie value in that function
const doSomething = (movie) => {
//Do some stuff with the movie
}

Related

Set heights of a row of components dynamically based on the tallest one

I have three components called blog cards that are rendered with an image and text. Depending on how long the text is the cards are of different heights. I want to render them, then get the tallest one, and sort of re-render them, so they are all the same height.
Here is the Page
import * as React from 'react'
import { SocialIconRow } from '#/components/social-icons'
import BlogPostCard from '#/components/BlogCard'
import Image from 'next/image'
import { useState, useEffect } from 'react'
import { FixedSizeList } from 'react-window'
function BlogPostCardsList({ cards }) {
const tallestCardHeight = useMemo(() => {
return Math.max(...cards.map(card => card.height))
}, [cards])
return (
<FixedSizeList
itemCount={cards.length}
itemSize={tallestCardHeight}
width={'100%'}
height={'100%'}
>
{({ index, style }) => <BlogPostCard style={style} {...cards[index]} />}
</FixedSizeList>
)
}
export default function MyComponent(props) {
const [cardHeight, setCardHeight] = useState(null);
const [maxHeight, setMaxHeight] = useState(0);
useEffect(() => {
const calculateHeight = () => {
const cards = document.querySelectorAll('.blog-post-card');
let heights = [];
cards.forEach(card => {
heights.push(card.clientHeight);
});
setMaxHeight(Math.max(...heights));
}
calculateHeight();
setCardHeight(maxHeight);
}, []);
return (
<>
<div className="container mx-auto flex flex-col">
<div className="container mx-auto flex">
<div className="w-1/2 pr-4">
<div className="text-4xl font-bold">Mike Borman</div>
<div className="text-lg mt-2">Writer, Content Creator and Developer on Cardano</div>
</div>
<div className="w-1/2 flex flex-col justify-center">
<div className="max-h-48 max-w-48 mx-auto my-auto">
<Image
src="/images/myfaceppgray.png"
alt="Picture of the author"
className="max-h-48 max-w-48"
width="150"
height="150"
unoptimized={true}
/>
</div>
<div className="mt-4">
<SocialIconRow className="social-icon-row" />
</div>
</div>
</div>
<div className="mt-8">
<div className="text-3xl font-bold">Featured Blogs</div>
<div className="grid grid-cols-3 gap-4 h-full mt-4 align-items-stretch">
<div style={{height: cardHeight}}>
<BlogPostCard
title="The Hydra Protocol Family — Scaling and Network Optimization for the Cardano Blockchain"
slug="the-hydra-protocol-family-scaling-and-network-optimization-for-the-cardano-blockchain"
imageslug="/images/hydra.png"
className="blog-post-card"
/>
</div>
<div style={{height: cardHeight}}>
<BlogPostCard
title="Ouroboros, A deep dive for non PhDs"
slug="ouroboros-a-deep-dive-for-non-phd"
imageslug="/images/ourobouros.png"
className="blog-post-card"
/>
</div>
<div className="h-full row-auto" style={{height: cardHeight}}>
<BlogPostCard
title="Ouroboros, A deep dive for non PhDs"
slug="ouroboros-a-deep-dive-for-non-phd"
imageslug="/images/ourobouros.png"
className="blog-post-card"
/>
</div>
</div>
</div>
</div>
</>
)
}
Here is the Card component:
import React from 'react'
import Link from 'next/link'
import Image from 'next/image'
function BlogPostCard(props) {
const { title, slug, imageslug } = props
return (
<Link href={`/blog/${slug}`}>
<a className="block flex flex-col justify-between rounded-md border-2 border-teal-400 transition-all duration-300 ease-in-out hover:scale-105 hover:shadow-lg">
<img className="rounded-t-md h-48 w-full object-cover" src={imageslug} alt="blog post cover" />
<span className="text-white text-2xl p-4">{title}</span>
</a>
</Link>
)
}
export default BlogPostCard
I tried dynamically rendering them then setting them, btw I have no idea really what Im doing there.
You actually have all but one class already to do this entirely in CSS. Just add h-full to your a tag inside the BlogPostCard component's Link. Then you can get rid of all of the JS. Optionally, you could also remove the justify-between or change it to justify-stretch so that the titles of the blog posts are directly beneath of the post cover images.
In the demo below, you can see the result by clicking run code snippet. Also, if you're upgrading to NextJS 13, it's worth noting that you no longer need (and in fact can't have) an a tag as a child of Link. I'd suggest using article as I've done below, which will be more semantically correct anyway.
function BlogPage({posts}) {
return (
<main className="container mx-auto my-8">
<div className="flex gap-4">
<div className="w-1/2">
<h1 className="text-4xl font-bold">Mike Borman</h1>
<h2 className="text-lg mt-2">
Writer, Content Creator and Developer on Cardano
</h2>
</div>
<div className="w-1/2 flex flex-col justify-center items-center">
<span className="w-[150px] h-[150px] bg-neutral-300 rounded-full grid place-content-center">author img here</span>
<span>social row here</span>
</div>
</div>
<section className="mt-8">
<header>
<h2 className="text-3xl font-bold">Featured Blogs</h2>
</header>
<div className="grid grid-cols-3 gap-4 h-full mt-4 align-items-stretch">
{posts.map((post) => (
<BlogPostCard key={post.id} {...post} />
))}
</div>
</section>
</main>
)
}
function BlogPostCard({ slug, imageslug, title,}) {
return (
<Link href={`/blog/${slug}`}>
<article className="flex flex-col justify-stretch h-full rounded-md border-2 border-teal-400 bg-neutral-600 transition-all duration-300 ease-in-out hover:scale-105 hover:shadow-lg">
<img
className="rounded-t-md h-48 w-full object-cover"
src={imageslug}
alt="blog post cover"
/>
<span className="text-white text-2xl p-4">{title}</span>
</article>
</Link>
)
}
/* Stubbing out next/link here since I can't run NextJS in code snippets */
function Link({ href, children, className }) {
return (
<a href={href} className={className}>
{children}
</a>
)
}
const root = ReactDOM.createRoot(document.getElementById("root"))
root.render(<BlogPage posts={[
{
id: 1,
title: 'The Hydra Protocol Family — Scaling and Network Optimization for the Cardano Blockchain',
slug: 'the-hydra-protocol-family-scaling-and-network-optimization-for-the-cardano-blockchain',
imageslug: 'https://d3lkc3n5th01x7.cloudfront.net/wp-content/uploads/2019/05/15233606/700-X-394.png',
},
{
id: 2,
title: 'Ouroboros, A deep dive for non PhDs',
slug: 'ouroboros-a-deep-dive-for-non-phd',
imageslug: 'https://www.almaviva.it/dam/jcr:6212e8ef-1ed6-40e2-a75f-b6fa7c814662/Blockchain_1280x720.jpg',
},
{
id: 3,
title: 'How Blockchain Is Used',
slug: 'how-blockchain-is-used',
imageslug: 'https://imageio.forbes.com/specials-images/imageserve/5f2a32ee3b52675a453e2881/Fascinating-Examples-Of-How-Blockchain-Is-Used-In-Insurance--Banking-And-Travel/960x0.jpg?format=jpg&width=960',
},
]} />
);
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.development.js"></script>
<div id="root"></div>

How to show a popup modal on page load in React js functional component

How to show a popup modal on page load in React js functional component.basically when the page loads the popup or modal should be visible automatically without any click
Most modals will have a prop to specify whether or not the modal should be open. You can simply set this to true on initialization.
Consider an example using a Dialog from the React UI library MUI:
const SimpleDialog = (props) =>
{
const [open, setOpen] = useState(true)
return (
<Dialog open = {open}>
<DialogTitle>Title</DialogTitle>
<DialogContent>...</DialogContent>
</Dialog>
)
}
The open prop of the Dialog is based on the value of the state variable, which is initialized as true. You can change this value as needed through various Dialog actions. To learn more about MUI Dialogs, see the docs.
For information on useState, see the React docs.
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
modalState: true
};
this.handleShow = this.handleShow.bind(this);
}
handleShow() {
this.setState({ modalState: !this.state.modalState });
}
render() {
return (
<div>
<div className={"modal fade" + (this.state.modalState ? " show d-block" : " d-none")} tabIndex="-1" role="dialog">
<div className="modal-dialog" role="document">
<div className="modal-content">
<div className="modal-header">
<h5 className="modal-title">My Profile</h5>
<button type="button" className="close" onClick={this.handleShow}>
<span>×</span>
</button>
</div>
<div className="modal-body">...</div>
<div className="modal-footer">
<button type="button" className="btn btn-secondary" onClick={this.handleShow}>Close</button>
<button type="button" className="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
</div>
);
}
}
ReactDOM.render(, document.getElementById('root'));
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css">

I want to be able to reuse Chip components made with Svelte

It is difficult to reuse the Chip components that are currently running in my project.
I would like to modify the code to make it easier to reuse.
For example, I want to make it as easy to use as this
let labels=["foo", "bar"];
<Chips labels="{labels}" >
Current source code
<script>
import { redirectUris } from '../../store/';
import close from '../../asset/icon/tip/close.svg';
function removeFromList(index) {
$redirectUris.splice(index, 1);
$redirectUris = $redirectUris;
}
</script>
<div class="chips">
{#each $redirectUris as uri, index}
<div class="chip">
<p class="chip-name">{uri}</p>
<button
on:click="{() => {
console.log(uri);
removeFromList(index);
console.log($redirectUris);
}}">
<img src="{close}" alt="close" />
</button>
</div>
{/each}
</div>
Remove the reference to your store and replace it with a property:
<script>
import close from '../../asset/icon/tip/close.svg';
export let labels = [];
</script>
<div class="chips">
{#each labels as label, index}
<div class="chip">
<p class="chip-name">{label}</p>
<button
on:click="{() => {
labels.splice(index, 1);
labels = labels;
}}">
<img src="{close}" alt="close" />
</button>
</div>
{/each}
</div>
You can then use it like you posted above. If you need to update the chips in your parent component, use bind which establishes a two-way binding:
<script>
import Chips from '..';
let labels=["foo", "bar"];
</script>
<Chips bind:labels />
If you need a "chip deleted" event, you can use event dispatchers for that: https://svelte.dev/docs#createEventDispatcher
<script>
import { createEventDispatcher } from 'svelte';
import close from '../../asset/icon/tip/close.svg';
export let labels = [];
const dispatch = createEventDispatcher();
</script>
<div class="chips">
{#each labels as label, index}
<div class="chip">
<p class="chip-name">{label}</p>
<button
on:click="{() => {
labels.splice(index, 1);
labels = labels;
dispatch('close', { label, index });
}}">
<img src="{close}" alt="close" />
</button>
</div>
{/each}
</div>

Why is this react component not displaying content loaded?

I'm working on this project and I want to display the content I got from the backend routes via axios to Showcase component. But the code doesn't give the output as expected the updated state console.log(cont) is working and no issue but it doesn't rendering contents.The app.js state is received by the component. I want to display the names. The child functional component as follows.
import React from 'react';
import {
Table,
Button
} from 'reactstrap';
function Showcase(props) {
const title = props.title;
const contents = props.contents;
let items_body = [];
items_body = contents.map(cont => {
console.log(cont)
if(cont.category === 'Men') {
return (
<div className="item_card" key={cont._id}>
<div className="itemC_right">
<div className="itemCR_topA">
<div className="itemCR_topA_title">{cont.name}</div>
</div>
</div>
</div>
)
}
else if(cont.category === 'Women') {
return (
<div className="lead content d-flex d-flex justify-content-center mb-3" key={cont.id}>
<div>Name : {cont.name}</div>
</div>
)
}
else if(cont.category === 'Kids') {
return (
<div className="lead content d-flex d-flex justify-content-center mb-3" key={cont.id}>
<div>Name : {cont.name}</div>
</div>
)
}
else
return (
null
)
})
return (
<div id="showcase">
<div id="showcase_card">
<div className="row">
<div className="col-sm-6 d-flex flex-row mt-1">
<h1 className="display-3 txt_secondary text-left" id="showcase_title">{title}</h1>
</div>
<div className="col-sm-6 d-flex flex-row-reverse mt-4">
<small className="txt_secondary text-right">Oreo is a online shopping store made just for you.</small>
</div>
</div>
<div>
{items_body}
</div>
</div>
</div>
)
}
export default Showcase;
The App.js class component
class App extends React.Component {
state = {
title: 'Oreo',
contents: []
}
changeState = (category,data) => {
this.setState({
title: category,
contents: data
})
}
handleNavigation = (e) => {
const option = e.target.innerHTML;
switch(option) {
case "Men":
axios.get('/api/items/men/2')
.then(res => {
this.changeState('Men',res.data);
// console.log(res.data)
})
break;
}
}
render() {
return (
<div>
<NavigationBar handleNavigation={this.handleNavigation} />
<Showcase title={this.state.title} contents={this.state.contents} />
<ItemWindow />
<BottomBar />
</div>
);
}
}
export default App;
In NavigationComponent.js when clicked on Men I'm sending it to App.js then it handles the click event. Why doesn't Showcase.js cannot show/render results? Help.
So I got rid of the if statements under the Showcase.js and could get my results. It seems that I was checking the category twice(in handleNavigation and here). I also added async and await as tonkalata's way.

How to display value in real time without refresh page with React and SocketIO?

I develop a basic application with NodeJS, React and SocketIO.
My NodeJS server sends socket to the React clients with a table of players (string value). I want display this table of players in the react view, and refresh it dynamically when it changes.
I tried some solutions but nothing works great. Have you ideas to do that or to improve my code ?
Thanks
Constructor : this.players[]
constructor(props){
super(props);
this.state = {
endpoint: "http://127.0.0.1:8080",
}
this.gameId = this.props.match.params.id;
this.players = [];
}
showPlayer : display list of players with cards
showPlayers = () => {
const classes = this.props;
let playersCards = [];
console.log(this.players);
this.players.foreach(function(p){
playersCards.push(
<Card className={classes.card}>
<CardHeader
avatar={
<Avatar style={{backgroundColor: "#00FF00"}} aria-label="Recipe">
R
</Avatar>
}
action={
<IconButton>
<MoreVertIcon />
</IconButton>
}
title={p}
subheader=""
/>
</Card>
)
}
return playersCards;
}
Socket.io : get the table of players updated
socket.on('ack-join-game', function(res){
this.players = res.dataGame.players;
});
Render :
const classes = this.props;
return(
<div className="GameConfig">
<h1>Salon de jeu</h1>
<div className="well" style={this.wellStyles}>
<h2>Informations</h2>
Id : {this.gameId}
<br></br>
<h2>Players (0/2)</h2>
<div id="cards">
</div>
{this.showPlayers()}
<form onSubmit={this.handleFormSubmit}>
<br></br>
<Button bsStyle="primary" type="submit" bsSize="large" block>
Lancer la partie
</Button>
</form>
</div>
<ToastContainer store={ToastStore}/>
</div>
)
}
You should store your players in the state of your component as changing them affects what is going to be rendered. Also, you can remove the endpoint if it is never going to change at runtime :
constructor(props){
super(props);
this.state = {
players = [],
}
this.gameId = this.props.match.params.id;
this.endpoint = "http://127.0.0.1:8080";
}
Then call setState to update players and refresh the component in your socket event :
socket.on('ack-join-game', res => {
this.setState({ players: res.dataGame.players })
});
Now, your players will need to be accessed via this.state.players instead of this.players.
You could also completely remove your showPlayers function using map:
const { players } = this.state
const { card } = this.props.classes
return (
<div className="GameConfig">
<h1>Salon de jeu</h1>
<div className="well" style={this.wellStyles}>
<h2>Informations</h2>
Id : {this.gameId}
<br></br>
<h2>Players (0/2)</h2>
<div id="cards">
</div>
{players.map(player =>
<Card className={card} key={player}>
<CardHeader
avatar={
<Avatar style={{ backgroundColor: "#00FF00" }} aria-label="Recipe">
R
</Avatar>
}
action={
<IconButton>
<MoreVertIcon />
</IconButton>
}
title={player}
subheader=""
/>
</Card>
)}
<form onSubmit={this.handleFormSubmit}>
<br></br>
<Button bsStyle="primary" type="submit" bsSize="large" block>
Lancer la partie
</Button>
</form>
</div>
<ToastContainer store={ToastStore} />
</div>
)

Resources