how to show/hide on the same component in Reactjs - reactjs

I'm newbie in React, and I try to hide an image after I click the same image and then show the dropdown component from other folder. How do I do that?
I'm current stuck in not being able to hide the same picture and it shows the same picture at different spot.
Or is there better way to do it?
Below is the code
import React from 'react';
import mind_zebra from '../../images/MindScribe-zebra.png';
import dropdown from '../DropDown/DropDown.js';
import './entry.css';
class Entry extends React.Component {
state = { hideZebraPic : false};
onClickHandler = () => {
this.setState( prev => ({ hideZebraPic : !prev.hideZebraPic }));
};
render() {
return (
<div>
<img src={mind_zebra} onClick={this.onClickHandler} className="MindZebraPic" alt="zebra"/>
{this.state.hideZebraPic ? <Entry /> : null}
</div>
);
}
}

In your code you are always rendering the image. There is no condition to not render it in your render function.
If I'm understanding properly what you want to achieve, the right code for the render function would be:
render() {
if (this.state.hideZebraPic) {
return <Dropdown />;
} else {
return <img src={mind_zebra} onClick={this.onClickHandler} />;
}
}
It could be also written like this:
render() {
return (
<div>
{!this.state.hideZebraPic && (
<img src={mind_zebra} onClick={this.onClickHandler} />
)}
{this.state.hideZebraPic && <Dropdown />}
</div>
);
}

Related

How to render a YouTube video upon button click in React?

I am new to React and am trying to build a video player page. Currently I have a super basic page in mind — I'd like to have one button that, when clicked, renders a YouTube video.
I've followed a resource that uses the npm react-player package so that I can just embed a Youtube Player as follows:
function YouTubePlayer () {
return (
<div>
<ReactPlayer
url="https://www.youtube.com/watch?v=ug50zmP9I7s"
/>
</div>
)
}
export default YouTubePlayer
However, instead of having the video display on the page as soon as it loads, I want it to only load when the button is clicked. I created a button and an event handler like this:
import { Component } from 'react';
import ReactPlayer from 'react-player';
class YouTubePlayer extends Component {
constructor(props) {
super(props);
}
handleYouTubeClick = () => {
return (
<div>
<ReactPlayer url="https://youtu.be/OXHCt8Ym9gw"/>
</div>
);
}
render() {
return (
<div>
<p>Video Player</p>
<button onClick={this.handleYouTubeClick}>YouTube</button>
</div>
);
}
export default YouTubePlayer
but no video gets rendered. Do I have to do something with states? I do not know how I would go about doing so. Again, I am very new to React, so please let me know if I am approaching this completely wrong. Thanks.
import { Component } from "react";
import ReactPlayer from "react-player";
class YouTubePlayer extends Component {
constructor(props) {
super(props);
this.state = {
isClicked: false
};
}
handleYouTubeClick = () => {
this.setState({
isClicked: true
});
};
render() {
return (
<div>
<p>Video Player</p>
<button onClick={this.handleYouTubeClick}>Youtube</button>
{this.state.isClicked && (
<div>
<ReactPlayer url="https://youtu.be/OXHCt8Ym9gw" />
</div>
)}
</div>
);
}
}
export default YouTubePlayer;
Here is the code to solve your problem.
class YouTubePlayer extends Component {
state = {
showYoutube: false,
}
ShowPlayer = () => {
if(this.state.showYoutube) {
return (
<div>
<ReactPlayer url="https://youtu.be/OXHCt8Ym9gw"/>
</div>
);
}
}
handleYouTubeClick = () => {
this.setState({
showYoutube: true,
})
}
render() {
return (
<div>
<p>Video Player</p>
<this.ShowPlayer />
<button onClick={this.handleYouTubeClick}>Youtube</button>
</div>
);
}
}
I hope this will help you.
Thanks

How to load a specific photo with dynamic URL with react.js

I have a component where a list of pictures is rendered and it works perfectly fine :
import { Component} from 'react'
import Header from '../Home/Header'
import Footer from '../Home/Footer'
import PhotoItems from './objet'
class Photos1930 extends Component {
render() {
return (
<div>
<Header />
<h2 className='titre bloc'>Photos 1930</h2>
<div className='bloc bloc__photo'>
{PhotoItems.map((val, key) => {
let id = val.id
let url = val.url
let lienImage = "/galerie/:" + (val.id)
return <div key={id}>
<a href={lienImage}>
<img className='photo' alt='Photo Charles-Quint' src={url}></img>
</a>
</div>
})}
</div>
<Footer />
</div>
)
}
}
export default Photos1930
I want to create an other component where i can load a specific picture when user click on a picture from the precedent list. I use the same logic but for some reason the picture doesn't load. I don't have any errors in my console but on my page i just have the standard icon for image with my alt.
All the pictures are on public folder.
I just don't understand why is it working on one component but not on the other one.
import { Component } from 'react'
import Header from '../Home/Header'
import Footer from '../Home/Footer'
import PhotoItems from './objet'
const url = window.location.pathname
const justId = parseInt((url.split(':')[1]))
function specificId(photo) {
return photo.id === (justId)
}
let justUrl = (PhotoItems.find(specificId).url)
console.log(justUrl)
class PickPhoto extends Component {
render() {
return (
<div>
<Header />
<div>
<h1>{justId}</h1>
<img className="bigPhoto" alt="Charles-Quint" src={justUrl}></img>
</div>
<Footer />
</div>
)
}
}
export default PickPhoto
EDIT1 : Here's my github repo : https://github.com/FranMori/CharlesQuint
and here's my netlify link : https://stoic-bohr-810e13.netlify.app/
You can click on "Galerie Photos" and then click on any picture to see the problem.
in your repo, this.justUrl is undefined. You need to add justUrl in the component's state and update it dynamically inside componentDidMount like below. I also added a / in src={/${this.state.justUrl}}
import { Component } from 'react'
import Header from '../Home/Header'
import Footer from '../Home/Footer'
import PhotoItems from './objet'
class PickPhoto extends Component {
constructor() {
super()
this.state = { justUrl: "" };
}
componentDidMount() {
const url = window.location.pathname
const justId = parseInt((url.split(':')[1]))
function specificId(photo) {
return photo.id === justId
}
let justUrl = (PhotoItems.find(specificId).url)
console.log(justUrl)
this.setState({justUrl})
}
render() {
return (
<div>
<Header />
<div>
<h1>{this.justId}</h1>
<img className="bigPhoto" alt="Charles-Quint" src={`/${this.state.justUrl}`}></img>
</div>
<Footer />
</div>
)
}
}
export default PickPhoto

Passing state to more than one child component in React

I'm having trouble understanding how to pass state as props to other child components in React. In my code, you can see I've got a component that takes input and maps it to my state array, displaying part of that data in another component, that's working just fine.
But the overall goal is that when a user clicks on an item they've added to the list, React Router kicks in and changes the view to the MovieDetails component, which will have extra information they've entered, like title, date and description.
I haven't even gotten to setting up react router because I can't seem to properly access state within the MovieDetails component. And then I'm not quite sure how to display the correct MovieDetails component with router.
import React, { Component } from 'react';
import { BrowserRouter as Router, Route, Link } from 'react-router-dom';
import './App.css';
class App extends Component {
constructor() {
super();
this.addMovie = this.addMovie.bind(this);
this.state = {
movies : []
};
}
addMovie(movie) {
let movies = this.state.movies;
movies.push(movie);
this.setState({ movies });
}
render() {
return (
<div className="wrapper">
<div className="container">
<div>
<h3 className="heading">Favorite Movies</h3>
</div>
</div>
<div>
<AddMovie addMovie={ this.addMovie }/>
<MovieList movies={ this.state.movies }/>
</div>
</div>
)
}
}
class AddMovie extends Component {
addMovie(event) {
event.preventDefault();
const movie = {
title : this.title.value,
year : this.year.value,
image : this.image.value,
desc : this.desc.value
}
this.props.addMovie(movie);
this.movieForm.reset();
}
render() {
return (
<div className="container">
<form ref={(input) => this.movieForm = input} onSubmit={(e) => this.addMovie(e)}>
<input ref={(input) => this.title = input} className="Input" type="text" placeholder="Title"/>
<input ref={(input) => this.year = input} className="Input" type="text" placeholder="Year"/>
<textarea ref={(input) => this.desc = input} className="Input" type="text" placeholder="Description"></textarea>
<input ref={(input) => this.image = input} className="Input" type="text" placeholder="Poster URL"/>
<button type="submit">Add</button>
</form>
</div>
)
}
}
class MovieList extends Component {
render() {
return (
<div>
{ this.props.movies.map( (movie, i) => <MovieListItem key={i} details={ movie }/> )}
</div>
);
}
}
class MovieListItem extends Component {
constructor(props) {
super(props);
this.toggleClass = this.toggleClass.bind(this);
this.state = {
active: false
};
}
toggleClass() {
const currentState = this.state.active;
this.setState({ active: !currentState });
}
render() {
const { details } = this.props;
return (
<div
className={this.state.active ? "red": null}
onClick={this.toggleClass}
>
<img src={details.image} alt=""/>
<hr/>
</div>
)
}
}
class MovieDetails extends Component {
render() {
return (
<div>
<p>title here</p>
<p>year here</p>
<p>description here</p>
<img src="image" alt=""/>
</div>
)
}
}
export default App;
The problem come from the way you try to access the input values. When you use ref, you get a React wrapper, not the real DOM element, so you can't access directly to .value or .reset(). You have to use the getDOMNode() method to get the DOM element. This worked for me :
const movie = {
title : this.title.getDOMNode().value,
year : this.year.getDOMNode().value,
image : this.image.getDOMNode().value,
desc : this.desc.getDOMNode().value
};
...
this.movieForm.getDOMNode().reset();
An other thing, when you setState something that uses the current state, you should use the callback instead :
addMovie(newMovie) {
this.setState(({movies: prevMovies})=> ({
movies: [...prevMovies, newMovie]
}));
}
See complete setState API from official doc
If I got it right, do you want to push to a new component (where the details should be accessible) when you're clicking on an item created from MovieList? If so, here are the steps you have to do:
If you want to push a new view you have to use something like browserHistory or hashHistory from 'react-router'. In this case I'll use browserHistory.
To access the state in MovieDetails component simply pass it through browserHistory.
Here is the way I used your code to push to a new view when an item from MovieList component is clicked:
import {Router, Route, browserHistory} from "react-router";
class Routes extends Component {
render() {
let props = this.props;
return (
<Router history={browserHistory}>
<Route path="/" component={App}/>
<Route path="/movie-details" component={MovieDetails}/>
</Router>
)
}
}
// Here is your App component
class App extends Component {
// ... your code
}
// ... your other classes
class MovieListItem extends Component {
// ... Constructor
// Here I'm pushing the new route for MovieDetails view
toggleClass(details) {
browserHistory.push({
pathname: '/movie-details',
state: details // pass the state to MovieDetails
});
// ... your code
}
render() {
const {details} = this.props;
return (
<div
// ... your code
onClick={this.toggleClass.bind(this, details)} // pass details to toggleClass()
>
// ... your code
</div>
)
}
}
// Here is your Movie Details component
class MovieDetails extends Component {
console.log('This props: ', this.props.location.state); // The details object should be logged here
// ... your code
}
// Export Routes instead of App
export default Routes;
Hope that helps!

access state of react component from other component

I have the following spinner
import React, { Component } from 'react'
import './Spinner.scss'
export default class Spinner extends Component {
constructor(props) {
super(props);
this.state = {showLoading: true};
}
render () {
return (
<div className="spinner">
<div className="double-bounce1"></div>
<div className="double-bounce2"></div>
</div>
)
}
}
and from other component I would like to show or hide this spinner here is the code of the component:
import React, { Component } from 'react'
import RTable from '../../../components/RTable/RTable'
import Spinner from '../../../components/Spinner/Spinner'
import CsvDownload from '../containers/CsvDownloadContainer'
export default class Table extends Component {
_renderBreadcrumb () {
const { breadcrumb, handleBreadcrumbClick } = this.props
return (
<ol className="breadcrumb">
{(breadcrumb || []).map(el => {
return (
<li key={el.datasetKey}>
<a onClick={() => { handleBreadcrumbClick(el.granularity, el.datasetKey, el.datasetKeyHuman) }}>
{el.datasetKeyHuman}
</a>
</li>
)
})}
</ol>
)
}
render () {
const { datasetRows, columns, metadata, showLoading } = this.props
return (
<div className="row">
<div className="col-sm-12">
{this._renderBreadcrumb()}
<RTable rows={datasetRows} columns={columns} metadata={metadata} />
{ this.props.showLoading ? <Spinner /> : null }
<CsvDownload />
</div>
</div>
)
}
}
as you can see I trying to show or hide the spinner using:
{ this.props.showLoading ? <Spinner /> : null }
but I'm always getting undefinde. Some help please.
You have to move this
constructor(props) {
super(props);
this.state = {showLoading: true};
}
to your <Table /> component, otherwise you access showLoading from <Table />'s props, but it is not passed from anywhere.
Then change also
{ this.props.showLoading ? <Spinner /> : null }
to
{ this.state.showLoading ? <Spinner /> : null }
To show / hide <Spinner /> just call this.setState({ showLoading: Boolean }) in your <Table /> component.

Why does React add class is="null"?

A beginner question: I am rendering a collection of items with React render function and I noticed that React automatically adds attribute is="null" to each rendered DOM element.
Why is React doing that? Is the key applied correctly or not? The respective code is:
export default class ItemList extends Component {
render() {
let { items } = this.props
items = items.map((item) => {
return <Item key={item.id} item={item} />
})
return (
<div>
{items}
</div>
)
}
}
export default class Item extends Component {
render() {
const { item } = this.props
return (
<div>
<h3>{item.attributes.name}</h3>
</div>
)
}
}
In the DOM, each div and h3 has attribute is="null"
<div is="null">
<h3 is="null">Item 1</h3>
</div>
This is Firefox issue and its already in pipeline
https://discuss.reactjs.org/t/is-null-attribute-on-every-tag/4032/7
https://github.com/facebook/react/pull/6896

Resources