ReactJS - Access key of container div on click? - javascript

Here is the code that I'm working on right now.
How can I access the key that I have on the container div? Right now I'm just trying to console.log it but ultimately, I need to pass the key to an action so I can make a call to an API.
Thanks for any advice.
I want to access the key on the container div
renderRecipes() {
return _.map(this.props.recipes, recipe => {
return (
<div className="card" style={cardStyle} key={recipe.idMeal}>
<img className="card-img-top" src={recipe.strMealThumb} alt="Recipe" />
<div className="card-body">
<h5 className="card-title">{recipe.strMeal}</h5>
<button className="btn btn-outline-primary" onClick={this.viewRecipe}>
View Recipe Details
</button>
</div>
</div>
)
})
}
render() {
console.log(this.props.recipes);
return (
<div>
<h2>Main Ingredient Search Page</h2>
<SearchField />
<div className="d-flex flex-row flex-wrap">
{this.renderRecipes()}
</div>
</div>
);
}
}

You can do it pretty easily with an anonymous function:
<button className="btn btn-outline-primary" onClick={() => this.viewRecipe(recipe.mealId)}>
View Recipe Details
</button>
But the best way would be to extract the recipe into it's own component. Then it's nicely encapsulated and doesn't re-render onclick references.
class Recipe extends Component {
onViewDetails = () => {
this.props.onItemClick(this.props.id);
}
render() {
const {
name,
thumbnail
} = this.props;
return (
<div className="card" style={cardStyle}>
<img className="card-img-top" src={thumbnail} alt="Recipe" />
<div className="card-body">
<h5 className="card-title">{name}</h5>
<button className="btn btn-outline-primary" onClick={this.onViewDetails}>
View Recipe Details
</button>
</div>
</div>
)
}
}
--
return _.map(this.props.recipes, recipe => (
<Recipe
key={recipe.idMeal}
id={recipe.idMeal}
thumbnail={recipe.strMealThumb}
name={recipe.strMeal}
onItemClick={this.viewRecipe}
/>
);

I think you could do something like this
renderRecipes() {
return this.props.recipes.map(recipe => {
return (
<div className="card" style={cardStyle} key={recipe.idMeal}>
<img className="card-img-top" src={recipe.strMealThumb} alt="Recipe" />
<div className="card-body">
<h5 className="card-title">{recipe.strMeal}</h5>
<button className="btn btn-outline-primary" onClick={() => this.viewRecipe(recipe.idMeal)}>
View Recipe Details
</button>
</div>
</div>
)
})
}
Now, in the onClick function you'll receive the key!

I think you can define your viewRecipe method in this way:
viewRecipe = recipe => e => console.log(recipe)
viewRecipe will be a function that receives a recipe as parameter and returns another function which will be used for the onClick method:
<button className="btn btn-outline-primary" onClick={this.viewRecipe(recipe)}>
Or you can use also the techniques described in the docs which are the following:
<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>

Related

Warning: Cannot update a component (`BrowserRouter`) while rendering a different component ('something')

I have tried everything but no solution. Please anybody help.
my partial code:
socialLogin.js
const SocialLogin = () => {
const [signInWithGoogle, googleUser, googleLoading, googleError] =
useSignInWithGoogle(auth);
return (
<div>
<div className=" d-flex justify-content-evenly ">
<button
onClick={() => signInWithGoogle()}
type="submit"
className="btn btn-outline-primary"
>
<img className="px-2" src={google} alt="" />
Sign in with Google
</button>
</div>
</div>
);
};
export default SocialLogin;

onClick of button triggering all the components to open - Reactjs

I implemented a Card component and basically generating a bunch of cards on some input data. I binded a setter function on button click on every card which basically expands and collapse it. Even after putting unique keys to the div is sort of triggering all the cards to open at once.
Here is the code piece:
import React, { useState } from 'react';
import PrettyPrintJson from './PrettyPrintJson';
import './Card.scss';
import '../App.scss';
const Card = (props) => {
const { data } = props;
const [collapse, toggleCollapse] = useState(true);
return (<div className="card-group">
{data.map((obj, idx)=>{
return <div className="card" key={`${idx}_${obj?.lastModifiedOn}`}>
<div className="card-header">
<h4 className="card-title">{`fId: ${obj?.fId}`}</h4>
<h6 className="card-title">{`name: ${obj?.name}`}</h6>
<h6 className="card-title">{`status: ${obj?.status}`}</h6>
<div className="heading-elements">
<button className="btn btn-primary" onClick={() => toggleCollapse(!collapse)}>Show Json</button>
</div>
</div>
<div className={`card-content ${!collapse ? 'collapse show' : 'collapsing'}`}>
<div className="card-body">
<div className="row">
<PrettyPrintJson data={ obj } />
</div>
</div>
</div>
</div>
})}
</div>
);
}
export default Card;
Create a component that manages it's own state and render that component.
const CardItem = ({ obj }) => {
const [collapse, toggleCollapse] = useState(true);
return (<div className="card">
<div className="card-header">
<h4 className="card-title">{`fId: ${obj?.fId}`}</h4>
<h6 className="card-title">{`name: ${obj?.name}`}</h6>
<h6 className="card-title">{`status: ${obj?.status}`}</h6>
<div className="heading-elements">
<button className="btn btn-primary" onClick={() => toggleCollapse(!collapse)}>Show Json</button>
</div>
</div>
<div className={`card-content ${!collapse ? 'collapse show' : 'collapsing'}`}>
<div className="card-body">
<div className="row">
<PrettyPrintJson data={ obj } />
</div>
</div>
</div>
</div>)
}
then render it like
{data.map((obj, idx)=> (<CardItem obj={obj} key={idx} />))}
I think you can declare a state which is a type of int. After then, you can use the if-statement of index(idx) and state.
Like this:
const [collapsedCardNumbers, toggleCollapseCard] = useState([]);
const addCardNumber = (idx, prevState) => {
const arr_cardNum = prevState
!arr_cardNum .includes(idx) && arr_cardNum .push(idx)
return arr_cardNum
}
...
{data.map((obj, idx)=>{
return <div className="card" key={`${idx}_${obj?.lastModifiedOn}`}>
<div className="card-header">
<h4 className="card-title">{`fId: ${obj?.fId}`}</h4>
<h6 className="card-title">{`name: ${obj?.name}`}</h6>
<h6 className="card-title">{`status: ${obj?.status}`}</h6>
<div className="heading-elements">
<button className="btn btn-primary" onClick={() => toggleCollapseCard(prevState => addCardNumber(idx, prevState))}>Show Json</button>
</div>
</div>
<div className={`card-content ${collapsedCardNumbers.includes(idx) ? 'collapse show' : 'collapsing'}`}>
<div className="card-body">
<div className="row">
<PrettyPrintJson data={ obj } />
</div>
</div>
</div>
</div>
})}

how to use DOM element in React

I want to do getElementById to give css effect and click to slide function.
how do I use DOM in react? Thank you in advance.
function Auth() {
//this part needs to be fixed
const signUpButton = document.getElementById('signUp');
const signInButton = document.getElementById('signIn');
const container = document.getElementById('body');
signUpButton.addEventListener('click', () =>
container.classList.add('right-panel-active'));
signInButton.addEventListener('click', () =>
container.classList.remove('right-panel-active'));
Here are the classnames that might help you understand my code better.
return (
<div className ="auth">
<div className="body" id="body">
<SignUp className="test" />
<SignIn className="test" />
<div className="slide__body">
<div className="slides">
<div className="slide SignUp__left">
<p>Already have an account?</p>
<button className="slide__btn" id='signUp' > Sign In </button>
</div>
<div className="slide SignIn__right">
<p>Not a Member?</p>
<button className="slide__btn" id='signIn' > Sign Up </button>
</div>
</div>
</div>
</div>
</div>
)
}
I guess the propose to use React is that fact you should interact in the component state.
I suggest you use State in your component and add some according to some interaction
function App() {
const [mode, setMode] = React.useState();
const handleMode = (mode) => {
setMode(mode);
};
const containerClasses =
mode === "signUp" ? "body right-panel-active" : "body";
return (
<div className="auth">
<div className={containerClasses} id="body">
<SignUp className="test" />
<SignIn className="test" />
<div className="slide__body">
<div className="slides">
<div className="slide SignUp__left">
<p>Already have an account?</p>
<button
className="slide__btn"
id="signUp"
onClick={() => handleMode("signIn")}
>
{" "}
Sign In{" "}
</button>
</div>
<div className="slide SignIn__right">
<p>Not a Member?</p>
<button
className="slide__btn"
id="signIn"
onClick={() => handleMode("signUp")}
>
{" "}
Sign Up{" "}
</button>
</div>
</div>
</div>
</div>
</div>
);
}
You should avoid direct modification of the dom in React. React assumes that it is the only piece of code modifying the dom, and so it won't know about any changes you make. This opens up the possibility of bugs where react changes something on the dom that you don't expect, or doesn't change something you do expect. A simple piece of code like yours won't have these bugs, but best to learn the react way now so you don't run into these issues with more complicated code.
The react way to do this is to pass onClick props to the elements that need it, and to have a state variable which controls the class names. For example:
import React, { useState } from 'react';
function Auth() {
const [showPanel, setShowPanel] = useState(false);
return (
<div className="auth">
<div className={showPanel ? "body right-panel-active" : "body"}>
<SignUp className="test" />
<SignIn className="test" />
<div className="slide__body">
<div className="slides">
<div className="slide SignUp__left">
<p>Already have an account?</p>
<button
className="slide__btn"
onClick={() => setShowPanel(false)}
>
Sign In
</button>
</div>
<div className="slide SignIn__right">
<p>Not a Member?</p>
<button
className="slide__btn"
onClick={() => setShowPanel(true)}
>
Sign Up
</button>
</div>
</div>
</div>
</div>
</div>
);
}

How to pass dynamic value to div element and then access it - React ?

I'm mapping all of my files
_renderItems = files =>
files
? files.map((item, i) => {
return <ProjectItemUser {...item} key={i} index={i} />;
})
: null;
and then I'm trying to display it ProjectItemUser
class ProjectItemUser extends Component {
render() {
return (
<div>
<div className="book_item">
<div className="book_header">
<h2>{this.props.name}</h2>
</div>
<div className="book_this">
<div className="book_author">{this.props.subject}</div>
<div className="book_bubble">
<strong>Study: </strong> {this.props.study}
</div>
<div className="book_bubble">
<strong>Grade: </strong> {this.props.grade}
</div>
<FontAwesomeIcon icon="trash" id="trash" />
</div>
</div>
</div>
);
}
}
This basically displays all the files, and each file is its own separate row. I would like to assign value to div element on each iteration, so I can control which file has been clicked.
I can access my id with: this.props._id
Should this be done using refs and if so, how ?
You should pass onClick function as parameter
_renderItems = files =>
files
? files.map((item, i) => {
return <ProjectItemUser {...item} key={i} index={i} onClick={() => { console.warn(item) } />;
})
: null;
class ProjectItemUser extends Component {
render() {
return (
<div>
<div className="book_item">
<div className="book_header">
<h2>{this.props.name}</h2>
</div>
<div className="book_this">
<div className="book_author">{this.props.subject}</div>
<div className="book_bubble">
<strong>Study: </strong> {this.props.study}
</div>
<div className="book_bubble">
<strong>Grade: </strong> {this.props.grade}
</div>
<FontAwesomeIcon icon="trash" id="trash" />
<Button onClick={this.props.onClick} label="Click on me" />
</div>
</div>
</div>
);
}
}

How do I add a post route to my react application

I have a modal with the following code in my components and I would like to add a post route to my code to capture the user's response. I have Mongo/Mongoose set up as well as a backend server. Any help would be amazing as I am new to React!
render() {
return(
<div className="modal column y-center">
<h3>How are you doing?</h3>
{!this.state.start ? (
<div className="choices">
<button onClick={() => this.startRelaxation('ok_images')}>Ok</button>
<button onClick={() => this.startRelaxation('neutral_images')}>Neutral</button>
<button onClick={() => this.startRelaxation('anxious_images')}>Anxious</button>
</div>
) : (
<div className="column y-center">
<div className="image">
<img src={this.state[this.state.mood][this.state.current_image]}/>
</div>
<button onClick={this.nextImage.bind(this)}>Next Image</button>
</div>
)}
<button onClick={this.props.closeModal}>Close</button>
</div>
)
}
}
I would recommend hooking up your startRelaxation() function to execute a HTTP request to your backend using a 3rd party library such as Axios.
Alternatively, given you are using MongoDB, you may find a database management tool such as Parse Server very useful.
This is just building off of Arman's post, but you can do something like this:
import axios from 'axios';
import React, {Component} from 'react';
class YouComponent extends Component {
constructor(props){
super(props);
this.startRelaxation = this.startRelaxation.bind(this);
}
startRelaxation(string){
axios.post('YourRoute'{'BODY OF REQUEST'})
.then(data => 'DO STUFF WITH DATA');
}
render() {
return(
<div className="modal column y-center">
<h3>How are you doing?</h3>
{!this.state.start ? (
<div className="choices">
<button onClick={() => this.startRelaxation('ok_images')}>Ok</button>
<button onClick={() => this.startRelaxation('neutral_images')}>Neutral</button>
<button onClick={() => this.startRelaxation('anxious_images')}>Anxious</button>
</div>
) : (
<div className="column y-center">
<div className="image">
<img src={this.state[this.state.mood][this.state.current_image]}/>
</div>
<button onClick={this.nextImage.bind(this)}>Next Image</button>
</div>
)}
<button onClick={this.props.closeModal}>Close</button>
</div>
)
}
}
You have the axios request in the startRelation method and you can do whatever you need to do in the DB.

Categories