I'm currently learning React js. My code work when it has one show hide password. But when i have more than one, i have struggle. This code work, because it has just one.
export default function App() {
const [changePassword, setChangePassword] = useState(true);
const changeIcon = changePassword === true ? false : true;
return (
<div className="wrapper-login">
<div className="wrapper-form">
<h2>Welcome Back!</h2>
<form>
<label>Email</label>
<div>
<input
type="email"
name="email"
required
/>
</div>
<label>Password</label>
<div className="form-group">
<input
type={changePassword ? "password" : "text"}
name="password"
required
/>
<span className="icon"
onClick={() => {
setChangePassword(changeIcon);
}}
>
{changeIcon ? <EyeOutlined /> : <EyeInvisibleOutlined />}
</span>
</div>
</form>
</div>
</div>
);
}
In codesandbox i have 3 input type password, and each input have show hide password. Can you help me to achieved that ? and explain to me why thats work ? . I'm sorry for my bad English. Thank you
You may create a component that controls hide or show behavior. For example, you can create a generic component for isolated show hide behavior. You pass the input name, and it creates a sub-component for you.
export default function ShowHidePassword({ name }) {
const [isVisible, setVisible] = useState(false);
const toggle = () => {
setVisible(!isVisible);
};
return (
<div className="form-group">
<input type={!isVisible ? "password" : "text"} name={name} required />
<span className="icon" onClick={toggle}>
{isVisible ? <EyeOutlined /> : <EyeInvisibleOutlined />}
</span>
</div>
);
}
usage:
<div>
<ShowHidePassword name="name" />
<ShowHidePassword name="password" />
</div>
when you use one state for more than one thing, state changes will effect on all of elements that use the state.
best way is create a reusable input component and import it anywhere and As much as you want. on this way every changes will happen just inside that component and wont effect on others component
dont forget to pass ...props to your input if you want access to the input onChange,name and ....
export const PasswordInput = (props) => {
const [hide, setHide] = useState(false);
const toggle = () => {
setHide((prev) => !prev);
};
return (
<div>
<input type={!isVisible ? "password" : "text"} {...props} required />
<i className="icon" onClick={toggle}>
{hide ? <EyeVisible /> : <EyeInvisible />}
</i>
</div>
);
}
usage:
<div>
<PasswordInput />
<PasswordInput />
<PasswordInput />
</div>
now every toggle will only effect on the clicked input and there is no side effect and re render
Related
So I have 2 components. SearchBar.js and ProductDetail.js
The searchBar JS help me to search product from my header. And when clicked it will redirect to another productDetail page. the problem is I got that take a number as the value, when I change it's number and then proceed to search another product. When I got redirected to that productPage, the input value will stay and not reset. How to fix this ?
Here's my code :
ProductDetail.js
const [productCount, setproductCount] = useState(0);
<input
type="number"
className='input-quantity'
value={productCount || 1}
onChange={(e) => {
setproductCount(parseInt(e.target.value))
}}
/>
SearchBar.js
<div className="searchInput">
<input
id="searchKeyInputId"
type="text"
placeholder={placeholder}
onChange={handleFilter}
ref={inputRef}
/>
<BiSearch className="input-append-icon" />
{filteredData.length !== 0 && (
<div className="searchResult">
{filteredData && filteredData.slice(0, 5).map((value) => {
return <Link
to={`/p/${value.id}/${value.slug}`}
className="searchItem"
key={value.id}
onClick={clearInput}
>
<p className='fontRegular'>{value.name}</p>
</Link>
})}
</div>
)}
</div>
I have a React app, where I'm using an input field as a searchbar, which upon typing, returns a list of products, and upon clicking any product takes you to that product page. I want to clear the typed text in the searchbar after the redirection to new page has happened but I haven't been able to achieve this yet.
I've tried many methods and went over similar posts, but I don't know what am I doing wrong as text is never cleared.
I'm using Material UI for rendering the list and have imported everything as needed.
Below is my code:
Navbar component (contains searchbar)
const Navbar = () => {
const [text, setText] = useState('');
const [liopen, setLiopen] = useState(true);
const getText = (text) => {
setText(text);
setLiopen(false);
};
const handleClick2 = (e) => {
setText('');
setLiopen(true)
};
return (
<header>
<nav>
<div className="middle">
<div className="nav_searchbar">
<span className="search_icon">
<SearchIcon id="search" />
</span>
<input
type="text"
onChange={(e) => getText(e.target.value)}
name=""
placeholder="Search for products, categories, ..."
id=""
/>
</div>
{text && (
<List className="extrasearch" hidden={liopen}>
{products
.filter((product) =>
product.title.toLowerCase().includes(text.toLowerCase())
)
.map((product) => (
<ListItem>
<NavLink
to={`/getproductsone/${product.id}`}
onClick={(e) => {handleClick2(e)}}
>
{product.title}
</NavLink>
</ListItem>
))}
</List>
)}
</nav>
</div>
</header>
);
};
export default Navbar;
You need to set the value of the input if you want it controlled by the component state.
<input value={text}
type="text"
onChange={(e) => getText(e.target.value)}
name=""
placeholder="Search for products, categories, ..."
id=""
/>
What I want to achieve is to be able to get all the new data on the next object that is added, also be able to click on the printed divs and get that current object to edit. I've built something, but the key logic is missing.
Problems:
Show current input fields
Be able to switch to the div (objects) and get the values in the input so I can edit
import { useState, useEffect } from 'react';
export default function AddQuiz() {
const [current, setCurrent] = useState(1);
const [questions, setQuestions] = useState([]);
function add_question() {
const dumb = {
id: `${Math.floor(100000 + Math.random() * 900000)}`,
question: `${Math.random().toString(36).substr(2, 5)}`,
anwser1: `${Math.random().toString(36).substr(2, 5)}`,
anwser2: `${Math.random().toString(36).substr(2, 5)}`,
anwser3: `${Math.random().toString(36).substr(2, 5)}`,
anwser4: `${Math.random().toString(36).substr(2, 5)}`,
};
setQuestions([...questions, dumb]);
}
return (
<>
<pre>
{' '}
{questions.map((item) => (
<div>
question: {item.question} anwser1: {item.anwser1} anwser2: {item.anwser2} anwser3: {item.anwser3} anwser4:{' '}
{item.anwser4}
</div>
))}{' '}
</pre>
<button onClick={() => add_question()}>add dump question</button>
<br />
<br />
<hr />
{questions.length !== 0 ? (
<form>
<input type="text" value={questions[0].question} />
<input type="text" value={questions[0].anwser1} />
<input type="text" value={questions[0].anwser2} />
<input type="text" value={questions[0].anwser3} />
<input type="text" value={questions[0].anwser4} />
</form>
) : (
'please add some question'
)}
</>
);
}
You need to add onChange in your input field and use it properly.
Here I've created a codesandbox, that you're looking for. https://codesandbox.io/s/redux-shop-cart-forked-z891d?file=/src/App.js
how about this:
const [que1, setQue1] = useState("");
function add_question() {
const dumb = {
question: que1 ? que1 : Math.random().toString(36).substr(2, 5),
};
setQuestions([...questions, dumb]);
}
<input
type="text"
onChange={(e) => setQue1(e.target.value)}
defaultValue={questions[0].question}
/>
try:
example
I am dynamically creating buttons from an API call that looks like this:
My goal is that when a button is clicked the inner text will display in the search bar above.
below is the code for this auto complete component:
const Autocomplete = (props) =>
{
const btnSearch = (e) => {
console.log(props.suggestions)
}
return(
<>
{props.suggestions.map((e) => (
<button className={style.btn} onClick={btnSearch} key={e}>{e}</button>
))}
</>
);
}
export default Autocomplete;
The Autocomplete component is then being placed in a div as seen here:
return (
<>
<div className={style.container}>
<div className={style.title_hold}>
<h1>turn one</h1>
<h2>a search engine and game companion for Magic: The Gathering</h2>
</div>
<input className={style.search} type='text' placeholder='search for cards here...' value={search} onChange={handleInputChange} onKeyPress={handleSubmit}></input>
<div className={style.btn_wrap}>
<Autocomplete suggestions={results} />
</div>
<div className={style.data_wrap} id='user_display'>
<div className={style.img_wrap}>
{photos}
</div>
<div className={style.display_info}>
<h2>{card.name}</h2>
<h2>{card.type_line}</h2>
<h2>{card.oracle_text}</h2>
</div>
</div>
</div>
</>
)
Any help would be appreciated.
You can create a state variable in your parent component and then pass a function to the Autocomplete's button for the onClick which will then update the state in the parent. Something like this:
const Autocomplete = (props) => {
return(
<>
{props.suggestions.map((e) => (
<button className={style.btn} onClick={() => props.setSearch(e)} key={e}>{e}</button>
))}
</>
);
}
export default Autocomplete;
Your parent component:
import React from 'react'
const ParentComponent = (props) => {
const [searchText, setSearchText] = React.useState("")
const handleClick = (textFromButtonClick) => {
setSearchText(textFromButtonClick)
}
return (
<>
<div className={style.container}>
<div className={style.title_hold}>
<h1>turn one</h1>
<h2>a search engine and game companion for Magic: The Gathering</h2>
</div>
<input className={style.search} type='text' placeholder='search for cards here...' value={searchText} onChange={handleInputChange} onKeyPress={handleSubmit}></input>
<div className={style.btn_wrap}>
<Autocomplete setSearch={handleClick} suggestions={results} />
</div>
<div className={style.data_wrap} id='user_display'>
<div className={style.img_wrap}>
{photos}
</div>
<div className={style.display_info}>
<h2>{card.name}</h2>
<h2>{card.type_line}</h2>
<h2>{card.oracle_text}</h2>
</div>
</div>
</div>
</>
)
}
export default ParentComponent;
I took over your input value in the parent component, but without seeing any of your other code, I have no idea how you're managing that but you can likely merge it into this workflow to wire it up.
Based on the official Giphy demo(CodeSandBox), I would like to create a live search function for Giphy GIFs.
And below is a demo of it.
search demo(CodeSandBox)
It holds the keyword as state and passes the keyword state to the search method of giphyFetch.
But the search results are not displayed.
Is there a problem with the code in the demo, or a solution to this problem?
Thank you.
source code
const giphyFetch = new GiphyFetch("sXpGFDGZs0Dv1mmNFvYaGUvYwKX0PWIh");
function App() {
const [keyword, setKeyword] = useState("");
const fetchGifs = (offset: number) =>
giphyFetch.search(keyword, { offset, limit: 10 });
return (
<>
<p>
<img src="./logo.gif" width="200" alt="Powered by GIPHY" />
</p>
<p>
input keyword
<input type="text" onChange={e => setKeyword(e.target.value)} />
</p>
<h4>search result</h4>
<Carousel fetchGifs={fetchGifs} gifHeight={200} gutter={6} />
</>
);
}
The Carousal does the fetchGifs once upon mount. So you need to force re-mount upon your input onChange. You can do this by adding dynamic key
Like this
...
<>
<p>
<img src="./logo.gif" width="200" alt="Powered by GIPHY" />
</p>
<p>
input keyword
<input
value={keyword}
type="text"
onChange={e => setKeyword(e.target.value)}
/>
</p>
<h4>search result</h4>
<Carousel
key={keyword}
fetchGifs={() => fetchGifs(5)}
gifHeight={200}
gutter={6}
/>
</>
...
Working demo is here