I want to take movie title when I click add to favorite button in movieItem.js and want to add my state in Favorites.js
import React, { Component } from 'react';
import { store } from '../..';
import './MovieItem.css';
class MovieItem extends Component {
render() {
const { Title, Year, Poster } = this.props;
console.log(this.props.Poster);
return (
<article className="movie-item">
<img className="movie-item__poster" src={Poster} alt={Title} />
<div className="movie-item__info">
<h3 className="movie-item__title">{Title} ({Year})</h3>
<button onClick={()=>console.log(Title)} type="button" className="movie-item__add-button">Добавить в список</button>
</div>
</article>
);
}
}
export default MovieItem;
That is my favoriteMovie.js
import React, { Component } from 'react';
import './Favorites.css';
class Favorites extends Component {
state = {
title: '',
movies: [
{ imdbID: 'tt0068646', title: 'The Godfather', year: 1972 }
]
}
render() {
return (
<div className="favorites">
<input value="Новый список" className="favorites__name" />
<ul className="favorites__list">
{this.state.movies.map((item) => {
return <li key={item.id}>{item.title} ({item.year})</li>;
})}
</ul>
<button type="button" className="favorites__save">Сохранить список</button>
</div>
);
}
}
export default Favorites;
Simply I want to take Title from Movie.js and add it to state which placed in favoriteMovie.js
Try to use context or redux to store your list of favourites movies and save there some important info like ID title etc etc and then on map check if some id is included in your list of favourites and if it is add some start there
Related
I was trying to add data in Gotocart.jsx and was using a nested map but nothing is showing up on the page.
The Gotocart.jsx is below
import React from 'react'
import { useState } from 'react'
import { data } from './Data'
import cartstyle from './cartstyle.css'
import Cartitems from './Cartitems';
import { infoarray } from './Menu';
import image73 from './assets/cake73.jpeg'
// import image73 from './assets/cake73.jpeg'
export default function Gotocart(props) {
return (
<div className='cartbody'>
<div className="heading">
<div></div>
<div className="welcome">
Welcome To the Cart
</div>
</div>
<div className="thanks">
<div></div> THANKS FOR VISITING
</div>
<div className="cart-info" id='cartinformation'>
{
data.map((e) =>{
return(
infoarray.map((ank) =>{
if(ank==e.id){
return (<Cartitems key={e.id} name1={e.name} images1 ={e.images}/>);
}
})
)
})
}
</div>
<div className="order">
<div></div>
ORDER NOW
</div>
</div>
)
}
This is the carditme.jsx which defines how a particular card will look like
import React from 'react'
import cartstyle from './cartstyle.css'
import { useState } from 'react';
import { data } from './Data';
import image73 from './assets/cake73.jpeg'
// below is destructuring
export default function Cartitems(props) {
return (
<div>
<div className="information">
<div className="imagecart">
<img className='img12' src={props.images1} alt="error" />
<div className="nameofitem"> {props.name1} </div>
</div>
<div className="quantity">
<button className="minus">-</button>
<button className="quantity">1</button>
<button className="add">+</button>
<i className="fa-solid fa-trash"></i>
</div>
</div>
</div>
)
}
The data stored in the infoarray is correct but still, something is wrong here. Moreover, when I am not using the outer map and clicking add to cart for 4 items, 4 cards show up in the Gotocart section.
edit->
This is the code where infoarray is defined
import React from 'react'
import images from './assets/cake21.jpeg'
import image1 from './assets/cake53.jpeg'
import image2 from './assets/cake61.jpeg'
import image3 from './assets/cake81.jpeg'
import image4 from './assets/cake78.jpeg'
import flower16 from './assets/flower16.jpeg'
import { data } from './Data'
import { Link } from 'react-router-dom'
const infoarray = [];
export { infoarray };
export const changedArray = newinfoArray => infoarray = newinfoArray;
export default function Menu(){
return (
<>
<div className="go" >
<Link to="/cart">
<i className="fa-solid fa-cart-shopping" />
</Link>
<div className="text">
Go to cart
</div>
</div>
</>
)
}
and data is like this
export const data = [
// all itmes
{
id:1 ,
name: "Almond Cake" ,
images : images01
},
{
id:2 ,
name: "Cartoon cake" ,
images : images02
},
{
id:3 ,
name: "Choco pie cake " ,
images : images03
},
}]
Way more data here.
You have to return some element or a fragment or null when there is no match also please check the key (I have mentioned as some_unique_key)
<div className="cart-info" id="cartinformation">
{data.map((e) => {
return infoarray.map((ank) => {
if (ank == e.id) {
return <Cartitems key={ank.some_unique_key} name1={e.name} images1={e.images} />;
}
return null;
});
})}
</div>
I can't figure out why I am not able to dynamically render my Movies component. I have a Movie Component that models each individual Movie. I then have a Movies component which maps every Movie from my api get request in index.jsx. It says, this.props.movies.map is not a function inside my Movies components. I quadrupled check that I was sending props the right way and it should be in the form of an array but nothing is working.
index.jsx:
import React from 'react';
import ReactDOM from 'react-dom';
import Movies from './components/Movies.jsx'
import axios from 'axios';
class App extends React.Component {
constructor(props) {
super(props)
this.state = {
movieList: [],
};
}
componentDidMount() {
axios.get('https://api.themoviedb.org/3/movie/550?api_key=f3a857449b25e45a2c69af11e38fe7de')
.then(res => {
this.setState({ movieList: res.data })
})
.catch(err => {
console.log(err);
})
}
render () {
return (
<div className="app">
<header className="navbar"><h1>Bad Movies</h1></header>
<div className="main">
<Movies
movies={this.state.movieList}
/>
</div>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('app'));
Movie.jsx:
import React from 'react';
class Movie extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<ul className="movie">
<li className="movie_item">
<img src={`https://image.tmdb.org/t/p/original/${this.props.movie.poster_path}`} />
<div className="movie_description">
<h2>{this.props.movie.title}</h2>
<section className="movie_details">
<div className="movie_year">
<span className="title">Year</span>
<span>{this.props.movie.release_date.split('-')[0]}</span>
</div>
<div className="movie_rating">
<span className="title">Rating</span>
<span>{this.props.movie.vote_average}</span>
</div>
</section>
</div>
</li>
</ul>
</div>
);
}
}
export default Movie;
Movies.jsx:
import React from 'react';
import Movie from './Movie.jsx'
class Movies extends React.Component {
constructor(props) {
super(props);
}
render() {
const mappedMovies = this.props.movies.map(movieObj => <Movie key={movieObj.id} movie={movieObj}/>); //This is where the error is pointing towards
return (
<div>
{mappedMovies}
</div>
);
}
}
export default Movies;
As Delice correctly said, there is a spelling mistake.
If you want this to be movie instead of movies, then change the below in index.js
<div className="main">
<Movies
movie={this.state.movieList}
/>
UPDATE:
Your API returns an object yet your state is set to an empty array as the initial value.
Then you populate your state movieList with the response from your API.
That means your movieList state actually becomes an object - therefor you get an error saying that
movies is not a function
You cannot map an object.
Remember to tell your component to only pass movieList when it is populated with data like so:
render () {
return (
<div className="app">
<header className="navbar"><h1>Bad Movies</h1></header>
<div className="main">
{this.state.movieList && <Movies
movies={this.state.movieList}
/> }
</div>
</div>
);
}
I have a react app with multiple components rendered on several different pages.
I built a search bar component, to be re-used and rendered on 5 different pages,
to filter thru the components contained on each page.
What I'm trying to achieve:
I want the search bar to filter whole components without using onClick buttons. It
needs to filter thru whole components with onChange the same way .filter() and onChange filters
thru an array list of text as the user types, and show only components that match keywords and hide the rest.
Issues I'm trying to solve in my current code:
The only way I can get whole components to filter, is to add and display them thru the SearchBar component itself,
but needs to operate and filter thru whichever the current pages components are instead of
using <Block /> in the SearchBar component to display them. SearchBar should only filter whichever
components are rendered on the current page. (Block was just used to test if it filters whole components)
The keywords in state of compList: will only work if they are the exact name of the component, but it
needs to be triggered with generic keywords like ["taco", "burrito"] etc. (somehow reference the keywords to
the actual components maybe?)
For some reason, if the user backspaces, all of the components in the <Block /> disappear. That
doesn't need to happen..needs to display all components until a match is found. (somehow it's altering the states compList maybe?)
SearchBar Component
import React from 'react';
import './search-bar-styles.scss';
import { FontAwesomeIcon } from '#fortawesome/react-fontawesome';
import { faSearch } from '#fortawesome/free-solid-svg-icons';
import { BreakfastBurritoRecipe, BreakfastTacoRecipe } from './recipe-box';
export class SearchBar extends React.Component {
constructor(props) {
super(props);
this.state = {
display: 'none',
value: '',
compList: ["BreakfastTacoRecipe", "BreakfastBurritoRecipe"]
};
this.showBar = this.showBar.bind(this);
this.hideBar = this.hideBar.bind(this);
this.userText = this.userText.bind(this);
};
showBar() {
this.setState({ display: 'block' });
};
hideBar() {
this.setState({ display: 'none', value: '' });
};
userText(event) {
const newList = this.state.compList.filter(item => item.includes(this.state.value))
this.setState({ value: event.target.value, compList: newList })
}
render() {
const _components = {
BreakfastTacoRecipe,
BreakfastBurritoRecipe
}
return (
<div>
<div id="searchButtonContainer" /*name={this.userText}*/>
<div id="searchButton" onClick={this.showBar}>
<FontAwesomeIcon icon={faSearch} />
</div>
</div>
<div id="searchContainer">
<div id="searchBox" style={{display: this.state.display}} onChange={this.showBar}>
<input value={this.state.value} onChange={this.userText} type="text" placeholder="Search.." />
<span id="closeSearchBtn" onClick={this.hideBar}>X</span>
<p>{this.state.value}</p>
<div>
{this.state.compList.map((component, index) => {
const Block = _components[component];
return <Block key={index} />
})}
</div>
</div>
</div>
</div>
)
}
};
Example of 1 of 5 pages where SearchBar will be rendered
import React from 'react';
import './breakfast-styles.scss';
import { Header } from './header.js';
import { BreakfastTitleBox } from './breakfast-title-box.js';
import { BreakfastTacoRecipe } from './recipe-box.js';
import { BreakfastBurritoRecipe } from './recipe-box.js';
import { OmeletteRecipe } from './recipe-box.js';
import { BiscuitsNGravyRecipe } from './recipe-box.js';
import { SausageBreakfastRollRecipe } from './recipe-box.js';
import { Footer } from './footer.js';
import ScrollArrow from './scrolltotop.js';
import { SearchBar } from './search-bar.js';
export class Breakfast extends React.Component {
render() {
return (
<div>
<ScrollArrow />
<Header />
<SearchBar /> <-----SearchBar being rendered on page
<BreakfastTitleBox />
<BreakfastTacoRecipe /> <----component to be filtered
<BreakfastBurritoRecipe /> <----component to be filtered
<OmeletteRecipe /> <----component to be filtered
<BiscuitsNGravyRecipe /> <----component to be filtered
<SausageBreakfastRollRecipe /> <----component to be filtered
<Footer />
</div>
)
}
}
Any suggestions? Examples?
I am a beginner in React, and I would like to make a web app with a dashboard like Windows tiles.
I generate them easily. But I want when I click in one of them, that hide the Dash menu and Display the sub-app "Prog1". And of course, reverse it. When I click the close button, it closes the sub-app and returns to the Dash menu (implying that it hides the Prog1 to display Dash).
I can hide the Dash menu with a function like this:
fctHide = () => {
this.setState({ isActive: false });
}
But how can I display the other subApp with maybe a function like fctShow?
Are we forced to put the function inside a class or just make a general display/hide function?
Is there an easier and newer way to do this (with hooks for example).
My app is on Codepen here : codepen
I can show you here on demand.
I'm surprised to see lots of questions or tutorials to show and hide elements from a button but not to switch between class/HTML/template etc. (like React Native router I guess).
Thanks!
Unless you are converting an old app to React, i.e. not writing a pure React app from the ground up, don't use ReactDOM.render multiple times. As you want to share the active state between components, it should live in their closest common ancestor.
I'm not sure how your dashboard should work, but here's a demo. Here, APP is such closest ancestor. You don't need react-router if you are not using URL routes or the History API.
import React from "react";
import "./styles.css";
class Dash extends React.Component {
render() {
const { isActive, fctHide, fctShow } = this.props;
const elements = ["1", "2", "3", "4"];
const items = [];
for (const [index, value] of elements.entries()) {
items.push(
<button
key={index}
onClick={() => {
fctShow(index);
}}
>
{value}
</button>
);
}
// if (isActive) {
return (
<div>
<table>
<tbody>
<tr>
<td> {items} </td>
</tr>
</tbody>
</table>
</div>
);
// } else {
// return null;
// }
}
}
class Prog1 extends React.Component {
render() {
const { isActive, selected, fctHide } = this.props;
if (isActive) {
return (
<div className="contProg1">
<button onClick={fctHide}>Close</button>
<h1>Program 1</h1>
<h2>Test1</h2>
<h2>Test2</h2>
<h2>Test3</h2>
Selected: {selected}
<ul>
<li>AAAAA</li>
<li>BBBBB</li>
<li>CCCCC</li>
</ul>
</div>
);
} else {
return null;
}
}
}
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = { isActive: true, selected: null };
}
fctShow = selected => {
this.setState({ isActive: true, selected });
};
fctHide = () => {
this.setState({ isActive: false });
};
render() {
const { isActive, selected } = this.state;
return (
<>
<Dash
isActive={isActive}
fctHide={this.fctHide}
fctShow={this.fctShow}
/>
<Prog1 isActive={isActive} selected={selected} fctHide={this.fctHide} />
</>
);
}
}
OK ! I finally use as proposed react-router. But I used the Hooks version (with <A>...)
So, the little dashboard is splitted in X parts :
The HTML with only the minimum and root.
<div id="root"></div>
The CSS (nothing to say more)
The sub apps in a specific folder "Apps"
import React from "react";
import { A } from "hookrouter";
class Prog1 extends React.Component {
render() {
return (
<div class="contProg1">
<button class="close">
{" "}
Close
</button>
<h1>Program 1</h1>
<h2>Test1</h2>
<h2>Test2</h2>
<h2>Test3</h2>
<ul>
<li>AAAAA</li>
<li>BBBBB</li>
<li>CCCCC</li>
</ul>
</div>
);
}
}
export default Prog1;
The router page to switch between apps and main Dash.
import React from "react";
import Prog1 from "./Apps/Prog1";
import Prog2 from "./Apps/Prog2";
import Prog3 from "./Apps/Prog3";
import Prog4 from "./Apps/Prog4";
import Dash from "./App";
const routes = {
"/": () => <Dash />,
"/Prog1": () => <Prog1 />,
"/Prog2": () => <Prog2 />,
"/Prog3": () => <Prog3 />,
"/Prog4": () => <Prog4 />
};
export default routes;
The main page, the Dashboard (App.js).
import React from "react";
import { A } from "hookrouter";
const elements = ["1", "2", "3", "4"];
function Dash() {
const items = [];
for (const [index, value] of elements.entries()) {
items.push(
<A href={"/Prog" + (index + 1)}>
<button key={index}>{value}</button>
</A>
);
}
return (
<div className="Dash">
<table>
<tr>
<td> {items} </td>
</tr>
</table>
</div>
);
}
export default Dash;
And to finish, the Index page :
import React from "react";
import { render } from "react-dom";
import "./styles.css";
import { useRoutes } from "hookrouter";
import routes from "./router";
import NoPageFound from "./Apps/404";
function App() {
const routeResult = useRoutes(routes);
return <div className="Dash">{routeResult || <NoPageFound />}</div>;
}
render(<App />, document.getElementById("root"));
It works well. I just need to add something like MemoryRouter or something else to hide the URL and prepare for mobile version.
I'm just a little bit scared when I will insert this part in a Django project.
Or, maybe I should separate it ? (You don't need to answer, I will close I think).
Thanks :)
I've a ButtonGroup as a radio buttons in navigation bar. I'd like to return a value of selected button in certain page. I've not much React experience and I'm a bit lost.
I have two .js-files: sidebar.js and page.js.
sidebar.js:
import React, { Component } from 'react';
import classNames from 'classnames';
import history from '../../core/history';
import {
Radio,
ButtonGroup,
Button } from 'react-bootstrap';
class Sidebar extends Component {
_onOptionChange(option) {
this.setState({
option: option
});
}
render() {
return (
<div>
...
...
...
<li>
<ButtonGroup vertical block data-toggle="buttons">
<Button className="btn btn-block" onClick={this._onOptionChange.bind(this, 'optionA')} active={this.state.option === 'optionA'}>Option A</Button>
<Button className="btn btn-block" onClick={this._onOptionChange.bind(this, 'optionB')} active={this.state.option === 'optionB'}>Option B</Button>
<Button className="btn btn-block" onClick={this._onOptionChange.bind(this, 'optionC')} active={this.state.option === 'optionC'}>Option C</Button>
</ButtonGroup>
</li>
...
...
...
</div>
);
}
}
export default Sidebar;
page.js:
import React, { PropTypes } from 'react';
import { PageHeader } from 'react-bootstrap';
const title = 'Page';
function displayPage(props, context) {
context.setTitle(title);
return (
<div>
<div className="row">
<div className="col-lg-12">
<PageHeader>Title</PageHeader>
</div>
<div className="col-lg-6">
{ value of selected radio button }
</div>
</div>
</div>
);
}
displayPage.contextTypes = { setTitle: PropTypes.func.isRequired };
export default displayPage;
How could I return the selected value?
Thanks!
From the React docs:
The state contains data specific to this component that may change over time.
In your Sidebar component, a click on the button will change the internal state of the Sidebar by calling this.setState({ ... }).
Consider the use of props when designing components:
Conceptually, components are like JavaScript functions. They accept arbitrary inputs (called "props") and return React elements describing what should appear on the screen.
So, in your case - I would think of Sidebar as a component that displays a list of options, and receives a callback function as its props. The callback function will be called from the Sidebar component by clicking one of the buttons, and will allow you to notify the containing component (the parent) of the click:
class SomethingThatUsesSidebar extends Component {
onSidebarOptionSelect(option) {
console.log(option);
}
render() {
return (
<div>
<Sidebar onOptionSelect={this.onSidebarOptionSelect.bind(this)} />
</div>
);
}
}
In your Sidebar component, you call the callback function like so:
class Sidebar extends Component {
// ...
_onOptionChange(option) {
this.props.onOptionSelect(option);
}
render() { ... }
}