trying to print duplicated component with react-to-print - reactjs

I have a component that I'm trying to print using react-to-print, is there any way I can print this component duplicated in one page?
here is my code:
import React, {useRef} from 'react';
import { useReactToPrint } from 'react-to-print';
import MyComponent from './myComponent';
import OtherComponent from './otherComponent';
const CreateAtt = () => {
const componentRef = useRef();
const printData = useReactToPrint({
content: () => componentRef.current,
documentTitle: 'doc',
});
return (
<>
<div className='d-flex justify-content-between'>
<div ref={componentRef}>
<MyComponent />
</div>
<OtherComponent />
</div>
<button className='btn btn-primary download-button' onClick={printData}>print</button>
</>
)
}
export default CreateAtt;

Related

My buttons dont work when i started my project on first load. Please helpme

`I am doing a spending money application. When i start my project by npm run start or refreshin page , my buttons dont work on first load. But if i do new changes and save but dont refresh the page or restart by npm run start , my buttons works. what is the reason ? i cant understand...
My app is like this :
My index.js:
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);
My app.js:
import ProductItem from './components/ProductItem';
import ShoppingCart from './components/ShoppingCart';
import MainContext from "./MainContext"
import './index.css';
import {data} from "./data.js"
import { useEffect, useState } from 'react';
function App() {
const products= [...data]
const [cartItems, setCartItems] = useState([])
const [cartTotal, setCartTotal] = useState(0)
const [mainMoney, setMainMoney] =useState(10000)
const context= {
products,
cartItems,
setCartItems,
cartTotal,
setCartTotal,
mainMoney,
setMainMoney,
}
return (
<MainContext.Provider value={context}>
<div className="app-container">
<div className='money-header'> Harcayacak <span> ₺ {mainMoney}</span> paranız kaldı!</div>
<div className='inner-container'>
{
products.map( item => <ProductItem item={item}/>)
}
</div>
<ShoppingCart/>
</div>
</MainContext.Provider>
);
}
export default App;
My MainContext.js
import { createContext } from "react";
const MainContext = createContext()
export default MainContext
My ShoppingCart.jsx component:
import React, { useContext } from 'react'
import MainContext from '../MainContext'
const ShoppingCart = () => {
let {
cartTotal,
setCartTotal,
cartItems,
setCartItems,
mainMoney,
setMainMoney } = useContext(MainContext)
const sepetiSifirla = () => {
console.log("sepet sifirlandii ")
}
return (
<div className='shopping-cart-container'>
<h3>Alışveriş Detayları</h3>
<div className='cart-item'>
<p>Cart Item <span className='item-quantity'> x1</span></p>
</div>
<hr/>
<div className='cart-footer'>
<button className='sepeti-sifirla' onClick={sepetiSifirla}>Sepeti Sıfırla</button>
<h3 className='cart-total'>Toplam: ₺ {cartTotal}</h3>
</div>
</div>
)
}
export default ShoppingCart
my ProductItem.jsx component:
import React, { useContext } from 'react'
import MainContext from '../MainContext.js'
const ProductItem = ({item}) => {
let {
cartItems,
setCartItems,
mainMoney,
setMainMoney } = useContext(MainContext)
const sat = (item) => {
console.log("sat",item)
}
const satinAl = (item) => {
console.log("satin al ",item)
}
return (
<div className='product-item'>
<div className='product-img'>
<img src={require(`${item.url}`)} alt={item.name} />
</div>
<h3> {item.name} </h3>
<p className='product-price'> ₺ {` ${item.price}`} </p>
<div className='product-buttons'>
<button className='sat-btn' onClick={() => sat(item)}>Sat</button>
<h4>{item.quantity}</h4>
<button className='satin-al-btn' onClick={() => satinAl(item)}>Satın Al</button>
</div>
</div>
)
}
export default ProductItem

React Context provider doesn't see data

I need to parse data from modal window (Modalbuy.js) to parent component (Page.js) and then to another child, but my Context Provider doesn't see changed data.Despite that fact, if I ask to console.log not in context.provider brackets, but still in parent component, I get my data logs right
Modalbuy.js
import React, {useState} from "react";
import "./modal.css";
import { DataBuyContext } from "../../page/page";
const Modalbuy = ({active, setActive,price}) => {
const [inputVolume, setInputVolume] = useState("")
function saveInput(event) {
setInputVolume(event.target.value)
console.log(inputVolume)
}
const {dataBuy, setDataBuy} = React.useContext(DataBuyContext)
function addBuy() {
setDataBuy([...dataBuy,{side: "BUY", price:{price},volume: {inputVolume},timestamp: new Date().toLocaleTimeString()}])
// console.log(dataBuy)
}
return (
<div className={active ? "modal active" : "modal"} onClick={() => setActive(false)}>
<div className="modal__content" onClick={e => e.stopPropagation()}>
<header>Make order</header>
<p>BUY {price}</p>
<input placeholder="Volume" value={inputVolume} onChange={saveInput}></input>
<div>
<button onClick = {addBuy}>Ok</button>
<button onClick={() => setActive(false)} >Cancel</button>
</div>
</div>
</div>
)
}
export default Modalbuy;
Page.js
import React, {useState} from 'react'
import Trading from '../trading/Trading'
import Archive from '../archive/Archive'
import './page.css';
export const DataBuyContext = React.createContext({})
const Page = () => {
const [dataBuy, setDataBuy] = useState([{}])
const [toggleState, setToggleState] = useState(1)
const toggleTab = (index) =>{
setToggleState(index);
}
console.log(dataBuy)
return (
<DataBuyContext.Provider value = {{dataBuy, setDataBuy}}>
<div className="container">
<div className="block-tabs">
<button
className={toggleState === 1 ? "tabs active-tabs" : "tabs"}
onClick={() => toggleTab(1)}>
Trading
</button>
<button
className={toggleState === 2 ? "tabs active-tabs" : "tabs"}
onClick={() => toggleTab(2)}>
Archive
</button>
</div>
<div className="content-tabs">
<div
className={toggleState === 1 ? "content active-content" : "content"}>
<Trading />
</div>
<div
className={toggleState === 2 ? "content active-content" : "content"}>
<Archive dataBuy= {dataBuy} />
</div>
</div>
</div>
</DataBuyContext.Provider>
);
}
export default Page;
And Archive.js child component, where I want to transport data
import React, {useState} from 'react';
import './archive.css';
import Table from './Table';
const Archive = (dataBuy) => {
const [rows, setRows] = useState(dataBuy)
console.log(rows)
return (
<Table dataBuy = {rows}/>
)
}
export default Archive;
App.js
import './App.css';
import React from 'react';
import Page from './components/page/page'
function App() {
return (
<div className="App">
<Page/>
</div>
);
}
export default App;

in MERN, Response given and using useState to update new state with new fetched data, but not visually visible in my website even though logic works

By using console.log(responseData.places) I have checked the fetching works since I am using a hook for this and seems to work fine until I setLoadedPlaces with is the method I use to update the loadedPlaces which I later use to get the values to fill the frontend part of the website.
This is the output I get from this console.log I did and the values are correct.
[{…}]
0: address: "sis se puede
busrespect: 'tu puedes',
creator: "6384e2f543f63be1c560effa"
description: "al mundial"
id: "6384e30243f63be1c560f000"
image:"https://upload.wikimedia.org/wikipedia/commons/thumb/1/10/Empire_State_Building_%28aerial_view%29.jpg/400px-Empire_State_Building_%28aerial_view%29.jpg"location: {lat: -12.086158, lng: -76.898019}
title: "Peru"
__v: 0
_id: "6384e30243f63be1c560f000"[[Prototype]]:
Objectlength: 1[[Prototype]]: Array(0)
So after this this the code I have in the frontend (SINCE the backend works properly) Let me know if you have any doubts with this logic
This is UserPlaces.js
import React, {useState, useEffect } from 'react';
import PlaceList from '../components/PlaceList';
import { useParams } from 'react-router-dom';
import { useHttpClient } from '../../shared/hooks/http-hook';
import ErrorModal from '../../shared/components/UIElements/ErrorModal';
import LoadingSpinner from '../../shared/components/UIElements/LoadingSpinner';
const UserPlaces = () => {
const {loadedPlaces, setLoadedPlaces} = useState();
const {isLoading, error, sendRequest, clearError } = useHttpClient();
const userId = useParams().userId;
useEffect(() => {
const fetchPlaces = async () => {
try {
const responseData = await sendRequest(
`http://localhost:5000/api/places/user/${userId}`
);
console.log(responseData.bus_stops)
setLoadedPlaces(responseData.bus_stops);
} catch (err) {}
};
fetchPlaces();
}, [sendRequest, userId]);
return (
<React.Fragment>
<ErrorModal error={error} onClear={clearError} />
{isLoading && (
<div className="center">
<LoadingSpinner />
</div>
)}
{!isLoading && loadedPlaces && <PlaceList items={loadedPlaces} />}
</React.Fragment>
);
};
export default UserPlaces;
This is Place-List.js
import React from 'react';
import "./PlaceList.css"
import Card from '../../shared/components/UIElements/Card'
import PlaceItem from './PlaceItem';
import Button from '../../shared/components/FormElements/Button';
const PlaceList = props => {
if (props.items.length === 0) {
return (
<div className='place-list-center'>
<Card>
<h2>No bus stops available. Be the first one to create one!</h2>
<Button to='/places/new'> Create Bus Stop </Button>
</Card>
</div>
);
}
return (
<ul className="place-list">
{props.items.map(bus_stops => (
<PlaceItem
key={bus_stops.id}
id={bus_stops.id}
image={bus_stops.image}
title={bus_stops.title}
busrespect={bus_stops.busrespect}
description={bus_stops.description}
address={bus_stops.address}
creatorId={bus_stops.creator}
coordinates={bus_stops.location}
/>
))}
</ul>
);
};
export default PlaceList;
This is PlaceItem.js
import React, { useState } from 'react';
import { useContext } from 'react';
import Card from '../../shared/components/UIElements/Card';
import Button from '../../shared/components/FormElements/Button';
import Modal from '../../shared/components/UIElements/Modal';
import Map from '../../shared/components/UIElements/Map';
import {AuthContext} from '../../shared//context/auth-context'
import "./PlaceItem.css";
const PlaceItem = props => {
const auth = useContext(AuthContext);
const [showMap, setShowMap] = useState(false);
const [showConfirmModal, setShowConfirmModal] = useState(false);
const openMapHandler = () => setShowMap(true);
const closeMapHandler = () => setShowMap(false);
const showDeleteWarningHandler = () => {
setShowConfirmModal(true);
};
const cancelDeleteHandler = () => {
setShowConfirmModal(false);
};
const confirmDeleteHandler = () => {
setShowConfirmModal(false); //when clicked close the new Modal
console.log('DELETING...');
};
return (
<React.Fragment>
<Modal show={showMap}
onCancel={closeMapHandler}
header={props.address}
contentClass="place-item__modal-content"
footerClass="place-item__modal-actions"
footer={<Button onClick={closeMapHandler}>Close </Button>}
>
<div className='map-container'>
<Map center={props.coordinates} zoom={16}/> {/* Should be props.coordinates but we writing default data for now until geocoding solved. */}
</div>
</Modal>
<Modal
show={showConfirmModal}
onCancel={cancelDeleteHandler}
header="Are you entirely sure?"
footerClass="place-item__modal-actions"
footer={
<React.Fragment>
<Button inverse onClick={cancelDeleteHandler}>
CANCEL
</Button>
<Button danger onClick={confirmDeleteHandler}>
DELETE
</Button>
</React.Fragment>
}
>
<p>
Do you want to proceed and delete this place? Please note that it
can't be undone thereafter.
</p>
</Modal>
<li className='"place=item'>
<Card className="place-item__content">
<div className='place-item__image'>
<img src={props.image} alt={props.title}/>
</div>
<div className='place-item__info'>
<h2>{props.title}</h2>
<h3>{props.address}</h3>
<p>{props.description}</p>
<p>{props.busrespect}</p>
</div>
<div className='place-item__actions'>
<Button inverse onClick={openMapHandler}> VIEW ON MAP</Button>
{auth.isLoggedIn && (<Button to={`/places/${props.id}`}> EDIT</Button> )}
{auth.isLoggedIn &&<Button danger onClick={showDeleteWarningHandler}> DELETE </Button>}
</div>
</Card>
</li>
</React.Fragment>
);
};
export default PlaceItem;
This is auth-context:
import { createContext } from "react";
export const AuthContext = createContext({
isLoggedIn: false,
userId: null,
login: () => {},
logout: () => {}});
This is is Modal.js
import React from 'react';
import ReactDOM from 'react-dom';
import Backdrop from './Backdrop';
import { CSSTransition } from 'react-transition-group';
import './Modal.css';
const ModalOverlay = props => {
const content =(
<div className={`modal ${props.className}`} style = {props.style}>
<header className={`modal__header ${props.headerClass}`}>
<h2>{props.header}</h2>
</header>
<form
onSubmit={
props.onSubmit ? props.onSubmit : event => event.preventDefault()
}
>
<div className={`modal__content ${props.contentClass}`}>
{props.children}
</div>
<footer className={`modal__content ${props.footerClass}`}>
{props.footer}
</footer>
</form>
</div>
);
return ReactDOM.createPortal(content, document.getElementById('modal-hook'));
};
const Modal = props => {
return (
<React.Fragment>
{props.show && <Backdrop onClick={props.onCancel} />}
<CSSTransition in={props.show}
mountOnEnter
unmountOnExit
timeout={200}
classNames="modal"
>
<ModalOverlay {...props}/>
</CSSTransition>
</React.Fragment>
);
};
export default Modal;
Also Trust the routing is correct since I have checked it already and I am just wondering if the logic in REACT with loadedPlaces, PlaceItema and PlaceList makes sense and it working. Let me know please. It will be really helpful.
Summary: Not getting any error but no visual data appears in the scren just the header of my website and the background (rest is empty) even though logic is functional.
const {loadedPlaces, setLoadedPlaces} = useState();
change the above line to
const [loadedPlaces, setLoadedPlaces] = useState();

React search bar to render cards dynamically

I have a movie app which displays a card for each movie in a state.
I would like to use a dynamic search bar to render movies corresponding to the search input value.
For instance, if I start to write "Har", I want to see only movies with a title that begins with "Har".
The app code :
import React, { useState, useEffect } from "react";
import "./App.css";
import Logo from "../components/Logo";
import Search from "../components/Search";
import Add_movie_button from "../components/Add_movie_button";
import Random_movie_button from "../components/Random_movie_button";
import Movie_card from "../components/Movie_card";
import axios from "axios";
const BASE_URL = "https://api.themoviedb.org/3/movie/";
const API_KEY = "4bcd155b9b8734cb8559319cdbfaf62f";
function App() {
const [movieinfos, setMovieinfos] = useState([]);
console.log(movieinfos);
useEffect(() => {
axios
.get("http://localhost:5000")
.then(function (response) {
const movies = response.data.movies;
console.log(response.data.movies);
return Promise.all(
movies.map((movie) =>
axios.get(
`${BASE_URL}${movie.movieid}?api_key=${API_KEY}&language=fr`
)
)
);
})
.then((responses) => {
console.log(responses);
setMovieinfos(
responses.map((response) => ({
Genres: response.data.genres,
Overview: response.data.overview,
Poster: response.data.poster_path,
Company: response.data.production_companies,
Release: response.data.release_date,
Title: response.data.title,
Id: response.data.id,
}))
);
});
}, []);
return (
<div className="App">
<div className="Header">
<Logo />
</div>
<div className="Menu">
<Search movieinfos={movieinfos} setMovieinfos={setMovieinfos} />
<Add_movie_button />
<Random_movie_button data={movieinfos} />
</div>
<div className="Movies">
{movieinfos.map((movie) => (
<Movie_card key={movie.Title} data={movie} />
))}
</div>
</div>
);
}
export default App;
The search bar code :
import React from "react";
import "./style.css";
const Search = (props) => {
console.log(props);
return (
<div className="Search">
<input
type="search"
id="Search_input"
placeholder="Rechercher un film ..."
value= //WHAT DO I NEED TO WRITE HERE ?
onChange={(event) =>
/*WHAT DO I NEED TO WRITE HERE ?*/ event.target.value
}
/>
</div>
);
};
export default Search;
You could create a state variable
[searchWord, setSearchWord] = useState('')
your input would then contain
value={searchWord}
onChange={e => setSearchWord(e.target.value)}
You could then filter your array movieinfos with the searchWord and map the returning array to display only the movies with the search world
movieinfos.filter(movie => movie.title.includes(searchWord)).map(movie => return <Movie_card key={movie.Title} data={movie} />)

Firebase - set() doesn't change the value, creates new doc instead

I'm trying to create read / unread chat option that will set the read value to true if opened.
When I do click the chat it opens the right db entry but doesn't set the value of read, instead it creates a new doc in my collection with read:true.
import {Avatar} from "#material-ui/core";
import StopRoundedIcon from "#material-ui/icons/StopRounded"
import "./Chat.css";
import ReactTimeago from "react-timeago";
import {selectImage} from "./features/appSlice";
import {useDispatch} from "react-redux";
import {db} from "./firebase";
import {useHistory} from "react-router-dom";
function Chat({id, username, timestamp, read, imageUrl, profilePic}) {
const dispatch = useDispatch();
const history = useHistory();
const open = () => {
if(!read) {
dispatch(selectImage(imageUrl));
db.collection("posts").doc(id).set(
{
read:true,
},
{merge:true}
);
history.push('/chats/view');
}
};
return (
<div onClick={open} className="chat">
<Avatar className="chat__avatar" src={profilePic} />
<div className="chat__info">
<h4>{username}</h4>
<p>Tap to view - <ReactTimeago date={new Date(timestamp?.toDate()).toUTCString()} /></p>
</div>
{!read && <StopRoundedIcon className="chat__readIcon" />}
</div>
)
}
export default Chat
Chat shouldn't be available for preview if the read value is true.
Preview that adds values to collection:
import {useSelector, useDispatch} from "react-redux";
import { useHistory } from "react-router-dom";
import {useEffect} from "react";
import {selectCameraImage, resetCameraImage} from "./features/cameraSlice";
import "./Preview.css";
import CloseIcon from "#material-ui/icons/Close";import TextFieldsIcon from '#material-ui/icons/TextFields';import CreateIcon from '#material-ui/icons/Create';import NoteIcon from '#material-ui/icons/Note';import MusicNoteIcon from '#material-ui/icons/MusicNote';import AttachFileIcon from '#material-ui/icons/AttachFile';import CropIcon from '#material-ui/icons/Crop';import TimerIcon from '#material-ui/icons/Timer';import SendIcon from '#material-ui/icons/Send';
import {v4 as uuid} from "uuid";
import {storage, db} from "./firebase";
import firebase from "firebase";
function Preview() {
const cameraImage = useSelector(selectCameraImage);
const history = useHistory();
const dispatch = useDispatch();
useEffect(() => {
if(!cameraImage) {
history.replace('/')
}
}, [cameraImage, history]);
const closePreview = () => {
dispatch(resetCameraImage());
};
const sendPost = () => {
const id = uuid();
const uploadTask = storage.ref(`posts/${id}`).putString(cameraImage, "data_url");
uploadTask.on('state_changed', null, (error) => {
console.log(error)
},
() => {
storage.ref('posts').child(id).getDownloadURL().then((url) => {
db.collection('posts').add({
imageUrl:url,
username:'Egon',
read:false,
//profilePic
timestamp:firebase.firestore.FieldValue.serverTimestamp(),
});
history.replace('/chats');
});
});
};
return (
<div className="preview">
<CloseIcon className="preview__close" onClick={closePreview} />
<div className="preview__toolbarRight">
<TextFieldsIcon />
<CreateIcon />
<NoteIcon />
<MusicNoteIcon />
<AttachFileIcon />
<CropIcon />
<TimerIcon />
</div>
<img src={cameraImage} alt="" />
<div onClick={sendPost} className="preview__footer">
<h2>Send Now</h2>
<SendIcon fontSize="small" className="preview__sendIcon" />
</div>
</div>
)
}
export default Preview
and Chats component that calls Chat function and passes id:
import {useState, useEffect} from "react";
import {Avatar} from "#material-ui/core";
import "./Chats.css";
import SearchIcon from "#material-ui/icons/Search";
import ChatBubbleIcon from "#material-ui/icons/ChatBubble";
import {db} from "./firebase";
import Chat from "./Chat";
function Chats() {
const [posts, setPosts] = useState([]);
useEffect(() => {
db.collection('posts').orderBy('timestamp', 'desc').onSnapshot(snapshot => setPosts(snapshot.docs.map(doc => ({
id:doc.id,
data:doc.data(),
}))))
}, [])
return (
<div className="chats">
<div className="chats__header">
<Avatar className="chats__avatar" />
<div className="chats__search">
<SearchIcon />
<input placeholder="Friends" type="text" />
</div>
<ChatBubbleIcon className="chats__chatIcon" />
</div>
<div className="chat__posts">
{posts.map(({id, data: {profilePic, username, timestamp, imageUrl, read}}) => (
<Chat key={id} username={username} timestamp={timestamp} imageUrl={imageUrl} read={read} profilePic={profilePic} />
))}
</div>
</div>
)
}
export default Chats
Found the solution, I forgot to add id in Chat component while maping them.
<div className="chat__posts">
{posts.map(({id, data: {profilePic, username, timestamp, imageUrl, read}}) => (
<Chat key={id} id={id] username={username} timestamp={timestamp} imageUrl={imageUrl} read={read} profilePic={profilePic} />
))}
</div>

Resources