I have react js code of inner most child component like this
import React from 'react'
import { addToCart } from 'actions/cart'
export default (props) => {
const { line_item, cart} = props
// const oClick = line_item.oClick.bind(line_item)
const handleClick = (id) => this.props.dispatch(addToCart(id, 1))
// *I am getting error above line*
return (
<div>
<ul className="ul-reset">
<li>
<div className="cart-prod-wrapper cf">
<div className="cart-image-wrapper">
<div className="cart-image">
<a href="#"><img src="#" alt="Product One"/>
</a>
</div>
</div>
<div className="cart-details">
<div className="cart-name">
{line_item.variant.name}
</div>
<div className="cart-price">{line_item.variant.price}</div>
</div>
<div className="cart-qty">
<div className="cart-qty-name">QTY:</div>
<div className="cart-qty-value">
<div class="minus"><span>-</span></div>
{line_item.quantity}
<div class="plus">
<span value = { line_item.variant.id } onClick={handleClick(line_item.variant.id)} >+</span></div>
</div>
</div>
<div className="cart-total">
<div className="cart-total-name">Total</div>
<div className="cart-total-value">{line_item.variant.price * line_item.quantity}</div>
</div>
</div>
</li>
</ul>
</div>
)
}
i want to perform to call an action using dispatch
and code of parent presentation component is line
export default (props) => {
const { account, cart, readMore1} = props
return (
<li>
{ !cart.isFetching && cart.line_items.map(
(line_item, i) => <CartPreview key = {i} line_item= {line_item} cart ={cart} />)
}
</li>
)
}
can any on please guide me to solve this error
Edit
const mapStateToProps = (state) => {
return {
account: getAccount(state),
cart: getCart(state),
classToSend: getReadmore(state),
authenticityToken: getAuthenticityToken(state)
}
}
export default connect(mapStateToProps)(HeaderContainer)
May be this could help
import React from 'react'
import { connect } from 'react-redux' // import connect from redux
import { addToCart } from 'actions/cart'
// name component to wrap it with connect
const MyComponent = (props) => {
const { line_item, cart} = props
return (
<div>
<ul className="ul-reset">
<li>
<div className="cart-prod-wrapper cf">
<div className="cart-image-wrapper">
<div className="cart-image">
<a href="#"><img src="#" alt="Product One"/>
</a>
</div>
</div>
<div className="cart-details">
<div className="cart-name">
{line_item.variant.name}
</div>
<div className="cart-price">{line_item.variant.price}</div>
</div>
<div className="cart-qty">
<div className="cart-qty-name">QTY:</div>
<div className="cart-qty-value">
<div class="minus"><span>-</span></div>
{line_item.quantity}
<div class="plus">
// used arrow function
<span value = { line_item.variant.id } onClick={() => props.dispatch(addToCart(line_item.variant.id, 1)} >+</span></div>
</div>
</div>
<div className="cart-total">
<div className="cart-total-name">Total</div>
<div className="cart-total-value">{line_item.variant.price * line_item.quantity}</div>
</div>
</div>
</li>
</ul>
</div>
)
}
export default connect()(MyComponent); // connect dispatch to component
Related
I rendered some elements with a functional component and I'm trying to select some of the elements to log them out to the console, but it logs out null. is there a special method used to select react elements?
This is my code:
let menuIcon = <i className=" bi bi-list" id="menu-icon"></i>
let cvIcon = <i className="bi bi-caret-down-fill"></i>
export default function Navbar() {
return (
<nav>
<div id="menu">
{menuIcon}
<div id="menu-list-container">
ABOUT
STACK
CONTACT
PROJECTS
</div>
</div>
<div id="logo">
<span id="v">V</span>
<span id="s">S</span>
<span id="c">C</span>
</div>
<div id="cv-container">
<button>
<input type="button" name="cv-btn" value="RESUME" id="cv-btn"/>
{cvIcon}
</button>
<div>
Download CV
View CV
</div>
</div>
</nav>
);
}
const root = document.getElementById("root");
createRoot(root).render(<Navbar></Navbar>);
const menuList = document.getElementById("menu-list-container")
console.log(menuList)
You cannot access the DOM right away after calling render; this is an asynchronous call.
A simple example involves using a basic setTimeout to wait a second after rendering.
const { useState } = React;
const { createRoot } = ReactDOM;
const menuIcon = <i className=" bi bi-list" id="menu-icon"></i>;
const cvIcon = <i className="bi bi-caret-down-fill"></i>;
const Navbar = () => {
return (
<nav>
<div id="menu">
{menuIcon}
<div id="menu-list-container">
ABOUT
STACK
CONTACT
PROJECTS
</div>
</div>
<div id="logo">
<span id="v">V</span>
<span id="s">S</span>
<span id="c">C</span>
</div>
<div id="cv-container">
<button>
<input type="button" name="cv-btn" value="RESUME" id="cv-btn" />
{cvIcon}
</button>
<div>
Download CV
View CV
</div>
</div>
</nav>
);
};
const root = document.getElementById("root");
createRoot(root).render(<Navbar></Navbar>);
setTimeout(() => {
const menuList = document.getElementById("menu-list-container");
console.log(menuList);
}, 1000);
<div id="root"></div>
<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>
Instead of a timeout, you can use a MutationObserver. This will guarantee that the element exists when it enters the DOM.
const { useState } = React;
const { createRoot } = ReactDOM;
// Adapted from: https://stackoverflow.com/a/65585776/1762224
const observe = (selector, targetNode = document.body) =>
new Promise(res => {
new MutationObserver(mutations =>
res([...mutations]
.flatMap((mutation) => [...mutation.addedNodes])
.find((node) => node.matches && node.matches(selector))))
.observe(targetNode, { childList: true, subtree: true });
});
const menuIcon = <i className=" bi bi-list" id="menu-icon"></i>;
const cvIcon = <i className="bi bi-caret-down-fill"></i>;
const Navbar = () => {
return (
<nav className="navbar">
<div id="menu">
{menuIcon}
<div id="menu-list-container">
ABOUT
STACK
CONTACT
PROJECTS
</div>
</div>
<div id="logo">
<span id="v">V</span>
<span id="s">S</span>
<span id="c">C</span>
</div>
<div id="cv-container">
<button>
<input type="button" name="cv-btn" value="RESUME" id="cv-btn" />
{cvIcon}
</button>
<div>
Download CV
View CV
</div>
</div>
</nav>
);
};
const root = document.querySelector('#root');
createRoot(root).render(<Navbar />);
observe('nav.navbar', root)
.then((menu) => {
const menuList = menu.querySelector('#menu-list-container');
console.log(menuList);
});
<div id="root"></div>
<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>
i'm creating a blog. in my index.js i have a left sidebar that shows the article links.
What I'm trying to do is when I click on the link the post content should be shown in the right sidebar of my index.js
At the moment it's been opened in a new page.
index.js
const IndexPage = ({
data: {
allMarkdownRemark: { edges },
},
}) => {
const PostData = edges[0]
const Posts = edges
.filter(edge => !!edge.node.frontmatter.date) // You can filter your posts based on some criteria
.map(edge => <PostLink key={edge.node.id} post={edge.node} />)
return (
<div className='html-container'>
<div className='main-container'>
<div className='row'>
<div className='left-sidebar'>
<div className='logo'>
<p>logo</p>
</div>
<div className='menu'>
{Posts}
</div>
<div className='social'>
<img src={twitch} />
<img src={discord} />
<img src={twitter} />
<img src={email} />
</div>
</div>
<div className='right-sidebar'>
</div>
</div>
</div>
</div>
)
}
post-link.js
import React from "react"
import { Link } from "gatsby"
const PostLink = ({ post }) => (
<div>
<Link to={"/blog"+post.frontmatter.slug}>
{post.frontmatter.title}
{/* {post.frontmatter.title} ({post.frontmatter.date}) */}
</Link>
</div>
)
export default PostLink
Check the API of the Link and if it has an equivalent of target attribute.
I am not sure what I'm missing here. I did a few search about this error but I can't not find anything that will on my error. The Home screen page will render all images. Prior to this, when a single image is clicked, it will open a new page to show the image. What i was trying to do is, when the image is clicked, i would like the image PLUS the detailed information of the image. All I get is an empty blank page with the error on dev tools (see below). Thank you in advance...
ProductScreen.js:18 Uncaught TypeError: Cannot read properties of undefined (reading 'params')
Here's the code:
import React, { useEffect } from 'react';
import Rating from '../components/Rating';
import { Link, useParams } from 'react-router-dom';
import { useDispatch, useSelector } from 'react-redux';
import LoadingBox from '../components/LoadingBox';
import MessageBox from '../components/MessageBox';
import { detailsProduct } from '../actions/productActions';
function ProductScreen(props) {
const dispatch = useDispatch();
const { id } = useParams();
console.log("A", id);
const productId = props.match.params.id; // this is the error as per dev tools
console.log(props.match.params.id);
const productDetails = useSelector((state) => state.productDetails);
const { loading, error, product } = productDetails;
useEffect = (() => {
dispatch(detailsProduct(productId));
}, [dispatch, productId]);
return (
//code here
)
}
export default ProductScreen;
[1]: https://i.stack.imgur.com/jdshU.png
Looks like you are not passing the props match while creating the JSX Element of ProductScreen. This line will look like this
<ProductScreen match={someMatchObj} />
As #mushroomator suggests you should also check if the value is undefined.
#mushroomator
This is my JSX...
return (
<div>
{loading ? (
<LoadingBox></LoadingBox>
) : error ? (
<MessageBox variant="danger">{error}</MessageBox>
) : (
<div>
<Link to="/">Back To Result</Link>
<div className="row top">
<div className="col-2">
<img className="large" src={product.image} alt={product.name} ></img>
</div>
<div className="col-1">
<ul>
<li>
<h1>{product.name}</h1>
</li>
<li>
<Rating
rating={product.rating}
numReviews={product.numReviews}
>
</Rating>
</li>
<li>
Price: ${product.price}
</li>
<li>
Description:
<p>{product.description}</p>
</li>
</ul>
</div>
<div className="col-1">
<div className="card card-body">
<ul>
<li>
<div className="row">
<div>Price</div>
<div className="price">${product.price}</div>
</div>
</li>
<li>
<div className="row">
<div>Status</div>
<div>
{product.countInStock > 0 ? (
<span className="success">In Stock</span>
) : (
<span className="danger">Unavailable</span>
)}
</div>
</div>
</li>
<li>
<button className="primary block">Add to Cart</button>
</li>
</ul>
</div>
</div>
</div>
</div>
)}
</div>
)
}
export default ProductScreen;
In the project I have a Upload image component that asks the user for an image and then previews it on the page. The image is not persay "uploaded" to any server and I hope that it does'nt need to. The goal is to be able to compare this uploded image with a random active set of images from an API (Image.js). What I have problem with is how to use the previewImage: URL.createObjectURL(event.target.files[0]) inside of another file, or at least that is what I belive to be the right way to think about it. (For context: The idea is to check the correlation between the uploaded file and the random active set.)
I have tried to implement an child to child state transfer but gave up when it did not work for the child to parent part. App.js is the parent, Image.js and image-upload.component.js are the children. I have also looked for ways to solve this with redux but don't understand how to store images or utilize states inside of the store. For this i only need to update the image state when files are selected by user.
To somewhat summarize and clarify the question: How can I transfer the chosen image file between two components and use the data in both of them?
This is my first project in React so the code may be caotic and full of "brute force" so I apologice in advance for that. Any help or guidence is greatly appreciated!
App.js:
import React from "react";
import "./App.css";
import Navbar from './components/Navbar/Navbar'
import "bootstrap/dist/css/bootstrap.min.css";
import UploadImages from "./components/image-upload.component";
import Images from "./components/Images";
function App() {
return (
<div className="App">
<Navbar />
<div className="container">
<div className="row">
<div className="col-5">
<div className="content">
<h3>Title</h3>
<h4>Upload my picture here</h4>
<UploadImages/>
</div>
</div>
<div className="col-2">
</div>
<div className="col-5">
<Images />
</div>
</div>
</div>
</div>
);
}
export default App;
Images.js (pure, brute force code i guess):
import UploadImages from "./image-upload.component";
import React, {useEffect, useState} from "react";
import "./Images.css";
function shuffleArray(array) {
let i = array.length - 1;
for (; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
const temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
}
function Images() {
const [urls, setURLs] = useState([]);
const [count, setCount] =useState(0)
useEffect(() => {
const urls = [
250940,
20622,
436625,
436444,
436509,
359245,
459090,
333933,
333916,
466350,
44831,
383010,
202660,
406317,
337349,
503448,
12617,
248662,
435805,
438545
].map(
(itemId) =>
`https://collectionapi.metmuseum.org/public/collection/v1/objects/${itemId}`
);
shuffleArray(urls)
Promise.all(
urls.map((currUrl) =>
fetch(currUrl)
.then((response) => response.json())
.then((data) => data.primaryImage)
.catch((error) => console.log("There was a problem!", error))
)
).then((fetchedUrls) => setURLs(fetchedUrls));
}, []);
if (count === 3) {
return (
<div>
<div class="imageContainer">
<div class="images__item">
<img class="photo" src={urls[1]} alt="" />
</div>
<div class="images__item">
<img class="photo" src={urls[2]} alt="" />
</div>
<div class="images__item">
<img class="photo" src={urls[3]} alt="" />
</div>
</div>
<button
onClick={() => setCount(4)}>
Next
</button>
</div>
)
}
if (count === 4) {
return (
<div>
<div class="imageContainer">
<div class="images__item">
<img class="photo" src={urls[1]} alt="" />
</div>
<div class="images__item">
<img class="photo" src={urls[2]} alt="" />
</div>
<div class="images__item">
<img class="photo" src={urls[3]} alt="" />
</div>
<div class="images__item">
<img class="photo" src={urls[4]} alt="" />
</div>
</div>
<button
onClick={() => setCount(3)}>
Previous
</button>
<button
onClick={() => setCount(5)}>
Next
</button>
</div>
)
}
if (count === 5) {
return (
<div>
<div class="imageContainer">
<div class="images__item">
<img class="photo" src={urls[1]} alt="" />
</div>
<div class="images__item">
<img class="photo" src={urls[2]} alt="" />
</div>
<div class="images__item">
<img class="photo" src={urls[3]} alt="" />
</div>
<div class="images__item">
<img class="photo" src={urls[4]} alt="" />
</div>
<div class="images__item">
<img class="photo" src={urls[5]} alt="" />
</div>
</div>
<button
onClick={() => setCount(4)}>
Previous
</button>
<button
onClick={() => {setCount(3); shuffleArray(urls);}}>
Reset
</button>
</div>
)
}
else {
return (
<div>
{/* <UploadImages upsideEmit={getStateFromChild} /> */}
<button
onClick={() => {shuffleArray(urls); setCount(3);}}>
Open
</button>
</div>
);
}
}
export default Images;
image-upload.component.js:
import React, { Component } from "react";
import UploadService from "../services/file-upload.service";
import "./Images"
class UploadImages extends Component {
constructor(props) {
super(props);
this.selectFile = this.selectFile.bind(this);
this.upload = this.upload.bind(this);
this.state = {
currentFile: undefined,
previewImage: undefined,
progress: 0,
message: "",
imageInfos: [],
};
}
componentDidMount() {
UploadService.getFiles().then((response) => {
this.setState({
imageInfos: response.data,
});
});
}
selectFile(event) {
this.setState({
currentFile: event.target.files[0],
previewImage: URL.createObjectURL(event.target.files[0]),
message: ""
});
}
upload() {
this.setState({
progress: 0,
});
UploadService.upload(this.state.currentFile, (files) => {
this.setState({
imageInfos: files.data,
});
})
}
render() {
const {
previewImage,
} = this.state;
return (
<div>
<div className="row">
<div className="col-8">
<label className="btn btn-default p-0">
<input type="file" accept="image/*" onChange={this.selectFile} />
</label>
</div>
<div className="col-4">
</div>
</div>
{previewImage && (
<div>
<img className="preview" src={previewImage} alt="" />
</div>
)}
</div>
);
}
}
export default UploadImages
In general you would want to useContext hook for this.
Check out this tutorial https://dev.to/email2vimalraj/react-hooks-lift-up--pass-down-state-using-usecontext-and-usereducer-5ai0
Hi i have problem using reactjs to reload the second component in parent component.
I have some 3 file 1 parent component 2 child component to make simple chat website.
The problem is my component Chatroom was not reload/change the data when i click the Chatlist in the second time.
This is my parent.js
import React, { useContext } from 'react'
import $ from 'jquery'
import Wrapper from '../components/wrapper'
import ChatList from './chat-list'
import ChatRoom from './chat-room'
export default class extends React.Component {
constructor(props) {
super(props)
this.state = {
login: 0,
user: null,
tokenChat: '',
roomChat: '',
isToken: false
}
this.clickChat = this.clickChat.bind(this)
}
componentDidMount() {
$('body').addClass('menu-position-side menu-side-left')
}
componentWillUnmount() {
$('body').removeClass('menu-position-side menu-side-left')
}
clickChat(token, room) {
let self = this
self.setState({
tokenChat: token,
roomChat: room,
isToken: true
})
}
render() {
return (
<Wrapper {...this.props} title="Dashboard" selected="dashboard" padding={false}>
{this.state.login == 1 &&
<div className="content-i">
<div className="content-box">
<div className="full-chat-w">
<div className="full-chat-i">
<div className="full-chat-left">
<div className="os-tabs-w">
<ul className="nav nav-tabs upper centered">
...
</ul>
</div>
<ChatList clickChat={this.clickChat} />
</div>
<div className="full-chat-middle">
{
this.state.isToken == false ?
null
:
<ChatRoom token={this.state.tokenChat} room={this.state.roomChat} />
}
</div>
<div className="full-chat-right">
<div className="user-intro">
<div className="avatar"><img alt="" src="/static/doctor-theme/img/avatar1.jpg" /></div>
<div className="user-intro-info">
<h5 className="user-name">John Mayers</h5>
<div className="user-sub">San Francisco, CA</div>
<div className="user-social"><i className="os-icon os-icon-twitter"></i><i className="os-icon os-icon-facebook"></i></div>
</div>
</div>
<div className="chat-info-section">
<div className="ci-header"><i className="os-icon os-icon-documents-03"></i><span>Shared Files</span></div>
<div className="ci-content">
<div className="ci-file-list">
<ul>
<li>Annual Revenue.pdf</li>
<li>Expenses.xls</li>
<li>Business Plan.doc</li>
</ul>
</div>
</div>
</div>
<div className="chat-info-section">
<div className="ci-header"><i className="os-icon os-icon-documents-07"></i><span>Shared Photos</span></div>
<div className="ci-content">
<div className="ci-photos-list">
<img alt="" src="/static/doctor-theme/img/portfolio9.jpg" />
<img alt="" src="/static/doctor-theme/img/portfolio2.jpg" />
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
}
</Wrapper>
)
}
}
Please Help Thank you.