how to use DOM element in React - javascript

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>
);
}

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;

Toggle between two components /buttons using react toggle hook {Show one component and Hide another}

I'm trying to create a Job platform, Where we can Sign up/login as either "Recruiter" or as a "Candidate". The complication I'm facing is I've created a form for both recruiter and candidate. Now I'm trying to switch between those componets. I've come this far
import useToggle from "#rooks/use-toggle"
export default function SignUp() {
const [recruitForm, setRecruitForm] = useToggle(true);
const [candidateForm, setCandidateForm] = useToggle(false);
}
return (
<div>
<form>
<div className="text-md tracking-wide p-0">
SignUp Form
</div>
<div className="flex flex-row gap-8">
<div>
<button
onClick={setRecruitForm}>
Recruiter
</button>
<>
{recruitForm && <RecruiterForm /> }
</>
</div>
<div>
<button
onClick={setCandidateForm}
type="button">
Candidate
</button>
<>
{candidateForm && <CandidateForm /> }
</>
</div>
</div>
</form>
</div>
</div>
)
}
Components are within their own context. But I have trouble even coming up with an idea how to handle or switch components without messing up the styling, the way it needs to be is when one instance opens, close the other conundrum / Form.
I'm sharing the output I've got using the useToggle react rooks
Any ideas on how to achieve it with any other hook or with useToggle hook itself or please let me know what I'm doing wrong.
https://www.loom.com/share/d2251bc3b9594782aa0a17aae92c997e {This is the result I've got}
Since thay are two Items you can make use of a boolean and just one state
const [active, setActive] = useState(false)
return (
<div>
<form>
<div className="text-md tracking-wide p-0">
SignUp Form
</div>
<div className="flex flex-row gap-8">
<div>
<button
onClick={()=>setActive(true)}>
Recruiter
</button>
<>
{active && <RecruiterForm /> }
</>
</div>
<div>
<button
onClick={()=>setActive(false)}
type="button">
Candidate
</button>
<>
{!active && <CandidateForm /> }
</>
</div>
</div>
</form>
</div>
</div>
)
}
as far as I can understand from your question, that you have created 2 from components for recruiter and candidate and want to show either on of em at a time. If not please do comment, I'll rectify the answer.
instead of checking your toggles when you will be rendering components, do before that, also you only need one toggle for this, better use a use state.
The initial false state for recruiter and true candidate
import React, {useState} from 'react';
export default function SignUp() {
const [switchForm, setSwitchForm] = useState(false);
return (
<div>
<form>
<div className="text-md tracking-wide p-0">
SignUp Form
</div>
<div className="flex flex-row gap-8">
<button
onClick={setSwitchForm(false)}>
Recruiter
</button>
<button
onClick={setSwitchForm(true)}
type="button">
Candidate
</button>
</div>
<div className="flex flex-row gap-8">
<>
{switchForm ? <CandidateForm /> : <RecruiterForm />}
</>
</div>
</form>
</div>
</div>
)};
This is not the actual/accurate code but just to give you the logical idea.
Also just a suggestion, use a custom hook for your parent component (signup.jsx) and put hooks there and import it from their to parent component and may come in use when you are going to submit the forms so that the states
and handler functions can have a common place to share.

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>
})}

ReactJS - Access key of container div on click?

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>

React mouseEnter event not working when on mapped children

I just want these child elements to show a remove button on mouseover...
console logging in handleMouseEnter shows that on render, ALL children fire the mouseEnter event. it seems stuck in a loop. debugging is next to impossible.
problems only arise when onMouseEnter and onMouseLeave are left in the code.
render(){
const handleMouseEnter = (tool) => this.setState({display : tool});
const handleMouseLeave = () => this.setState({display : "none"});
return (
<div>
<div className="search-result-background">
<div className="search-result-row row">
<div className="col-md-4">
</div>
<div className="col-md-4">
<form>
<TextFieldGroup className="find-tool-search-bar"
onChange= {this.checkToolExists}
value = {this.state.toolname}
field = 'toolname'
label = ''
error = {this.state.errors}
placeholder = "FIND IN FAVORITES"
/>
</form>
</div>
<div className="col-md-4">
<ButtonToolbar>
<DropdownButton noCaret onSelect={this.sort} bsSize="large" title="Sort by" id="dropdown-size-large">
<MenuItem eventKey="1">Name</MenuItem>
<MenuItem eventKey="2">Uploaded Date</MenuItem>
</DropdownButton>
</ButtonToolbar>
</div>
<h1 className="search-error">{this.state.errors}</h1>
<div className="col-md-12" >
{this.state.filteredTools.map((tool,i)=>
<div key ={i} className={"child " + tool.toolname } onMouseEnter={handleMouseEnter(tool.toolname)}
onMouseLeave={handleMouseLeave}> {this.state.display == tool.toolname ?
<button >remove?</button> : null}
<Link to={`/tools/${tool.id.substring(4)}`}>
<Thumbnail
className="thumb" src={logoImagePurple} alt="242x200">
<h3>{tool.toolname}</h3>
</Thumbnail>
</Link>
</div>
)}
</div>
</div>
</div>
</div>
)
}
}
The problem is this line:
onMouseEnter={handleMouseEnter(tool.toolname)}
You should change it to:
onMouseEnter={() => handleMouseEnter(tool.toolname)}

Categories