React newbie here,
I have a component for login which has two states (logged and not), and a button, a button click makes a form appear for the user.
function Main() {
const [state, setState] = useState(false);
function buttonClick(event) {
state = !state;
}
return (
<div id='main'>
<p id='main-body'>{lorem}</p>
{ state ? <LoginForm /> : <LoginButton />}
</div>
)
}
my issue is that the onClick itself (and the button) are in another component:
function LoginButton() {
return (
<div class="btn-centered">
<button type="button" class="btn btn-outline-primary btn-lg btn-centered" onClick={}>Login</button>
</div>
)
}
Have I understood the concept wrongly? How do I achieve the result I want with the outside component?
Thanks a lot for any help, I'd VERY appreciate explanations so I can learn.
You can pass buttonClick method in login button component like this
<LoginButton onClick={buttonClick} />
and inside Loginbutton component you can do something like this
<button type="button" ... onClick={props.onClick}>Login</button>
so when you click login button it will trigger you buttonClick method.
the LoginButton should get props and return a callback to the Main that will switch the state and you should also use useState to change the state in order to change the DOM,
thats how it should look
function Main() {
const [state, setState] = useState(false);
function buttonClick(event) {
setState((prev) => !prev);
}
return (
<div id='main'>
<p id='main-body'>{lorem}</p>
{ state ? <LoginForm /> : <LoginButton callback={buttonClick} />}
</div>
)
function LoginButton(props) {
const {callback} = props;
return (
<div class="btn-centered">
<button type="button" class="btn btn-outline-primary btn-lg btn-centered" onClick={callback}>Login</button>
</div>
)
}
Related
I implemented a Modal which uses a custom Hook in my App that should function as a login mask for a WiFi network. So far the Modal is working and I also already managed to pass the name of the selected SSID to it. However I'm struggling with getting back a variable into my other component from where I launched the modal.
Modal.js:
import React from 'react';
import { createPortal } from 'react-dom';
const Modal = ({ isShowing, connect, ssid, hide }) => isShowing ? createPortal(
<React.Fragment>
<div className="modal-overlay" />
<div className="modal-wrapper" aria-modal aria-hidden tabIndex={-1} role="dialog">
<div className="modal">
<div className="modal-header">
<button type="button" className="modal-close-button" data-dismiss="modal" aria-label="Close" onClick={hide}>
<span aria-hidden="true">×</span>
</button>
</div>
<div className="modal-body">
<p>Connect to: {ssid}</p>
<label>
<form onSubmit={connect}>
<input
id="password"
name="Password"
type="password"
value={"password"}
/>
<button type="submit">Connect</button>
</form>
</label>
</div>
</div>
</div>
</React.Fragment>, document.getElementById("modal")
) : null;
export default Modal;
useModal.js:
import { useState } from 'react';
const useModal = () => {
const [isShowing, setIsShowing] = useState(false);
const [password, setPassword] = useState("password");
function toggle() {
setPassword("HOW");
setIsShowing(!isShowing);
}
return {
password,
isShowing,
}
};
export default useModal;
Settings.js:
import React from "react";
import { useState, useEffect } from "react";
import Modal from "../../components/Modal";
import useModal from "../../components/useModal";
const electron = window.require('electron');
const { ipcRenderer } = electron;
const Settings = ({ reqReload }) => {
const [wifiList, setWifiList] = useState([{ id: "", ssid: 'No Networks available' }]);
const [ssidSelected, setSsidSelected] = useState("127.0.0.1");
const { isShowing, toggle } = useModal();
const updateWifi = (event, args) => {
setWifiList(args);
};
function openDialogue(ssid) {
setSsidSelected(ssid);
toggle();
};
/*
function connectWifi(password) {
console.log("Aktuelles Passwort: ", password);
toggle();
}
*/
useEffect(() => {
ipcRenderer.send('updateWifi');
ipcRenderer.on('wifi_list', updateWifi);
return function cleanup() {
ipcRenderer.removeListener('wifi_list', updateWifi);
};
}, []);
return (
<div className="settings">
<Modal
isShowing={isShowing}
connect={connectWifi}
ssid={ssidSelected}
hide={toggle}
/>
<div className="settings__header">
<h2></h2>
</div>
<div className="settings__body">
<div className="settings__connections">
<div className="settings__connections__wifi">
<p><i>Available Wifi-Networks:</i></p>
<div className="settings__connections__wifi__list">
{wifiList.map((item, i) => (
<div className="settings__connections__wifi__list__item" key={i}>
<button className="selectNetworkButton" type="button" onClick={() => openDialogue(item.ssid)}>{item.ssid}</button>
</div>
))}
</div>
</div>
</div>
</div>
</div>
)
};
export default Settings;
The code above already contains some things I tried. As stated before, passing the SSID to the modal worked, but I dont have a clue how to get the password back to Settings.js to handle the data there.
I'd be happy if someone can point me in the right direction!
in order to get back a variable from a child component, you can have the variable you would like to get back as a state in your parent component:
const [yourVariable, setYourVariable] = useState('')
then pass setYourVariable as a props to your modal.
this way you can set youVariable from inside the modal component, and get back its value this way :
// inside modal component
setYoutVariable(...)
I stumbled over another article just now and it seems like using a stateless component as my model leads to a dead end. Will have to convert it to a stateful component in order to extract the data from the form.
I am trying to use useContext to create a generic Tooltip component that passes a close() function to the content inside the Tooltip. I have written my Tooltip like this
export function Tooltip(props) {
const [active, setActive] = useState(false);
const close = () => {
setActive(false);
}
return (
<div className="tooltip-wrapper"
onClick={() => setActive(true)}
>
{props.children}
<TooltipContext.Provider value={{close}}>
{active && (
<div className='tooltip-tip bottom' ref={node}>
{props.content}
</div>
)}
</TooltipContext.Provider>
</div>
)
}
I create the Tooltip in a different class component as follows
function Category(props) {
return (
<Tooltip content={<AddCategoryInnerTooltip name={props.name}/>}>
<p className="tooltip-name-opener">{props.name}</p>
</Tooltip>
);
}
function AddCategoryInnerTooltip(props) {
const {close} = useContext(TooltipContext);
return(
<div className="inner-tooltip-wrapper">
<input
className="tooltip-custom-input"
type="text"
defaultValue={props.name}
/>
<div className="button-end">
<button onClick={close}>Cancel</button>
<button>Ok</button>
</div>
</div>
)
}
When I attempt to call close within the AddCategoryInnerTooltip, the state passed from the Tooltip component doesn't update. When I console.log the state, it always comes as true without changing. What am I doing wrong?
should be a callback function
<button onClick={()=>close}>Cancel</button>
So basically I want to hide a Button when I press on it.
const Button=()=>{
const [hideButton, setHideButton]= React.useState(false)
function Button(){
setHideButton(false)
}
return(
<div>
<button onClick={setHideButton}> </button>
</div>
)
}
Initially make it true to show the button. hide it based on click.
const Button=()=>{
const [hideButton, setHideButton]= React.useState(true)
function handleClick(){
setHideButton(false)
}
return(
<div>
{hideButton && <button onClick={handleClick}>Click</button>}
</div>
)}
Or just put !(Not) before hideButton -> !hideButton and make it true on button click.
const Button=()=>{
const [hideButton, setHideButton]= React.useState(false)
function handleClick(){
setHideButton(true)
}
return(
<div>
{!hideButton && <button onClick={handleClick}>Click</button>}
<ChildComponent hideButton={hideButton} handleClick={handleClick}/>
</div>
)}
function ChildComponent ({hideButton, handleClick}) {
return (
<>
<button onClick={handleClick}>Child Button</button>
{!hideButton && <p>
This is content/paragraph which will be hidden
based on based on button click from parent component.
</p>}
</>
)
}
You can change as per your requirement i have passed function and state variable to child component. child button will toggle your content of child component and parent button hide itself once clicked.
Just conditionally render the button so it doesn't render if hideButton is true:
return(
<div>
{!hideButton && <button onClick={setHideButton}> </button>}
</div>
)
It is needed to use React hook for doing this.
const Button=()=>{
const [hideButton, setHideButton]= React.useState(false)
function hide(){
setHideButton(false)
}
return(
<div>
{!hideButton && <button onClick={hide}> </button>}
</div>
)
}
There are several things going wrong here.
This is the way your code should look (one of many ways)
const Button = () => {
const [hideButton, setHideButton] = React.useState(false)
function handleHideButton() {
setHideButton(true)
}
return (
<div>
{!hideButton ? <button onClick={handleHideButton}>Hide</button> : null}
</div>
)
}
What you were doing wrong:
const Button=()=>{
const [hideButton, setHideButton]= React.useState(false)
// You're creating this function called Button, but should be called something esle like handleHideButton
function Button(){
// You should be setting this to true when the button is clicked.
setHideButton(false)
}
return(
<div>
// here you should be calling the handleHideButton function defined above. Calling setHideButton isn't a good option here.
<button onClick={setHideButton}> </button>
</div>
)
}
I am trying to set a basic like item, similar to facebook likes to be a color of black when the page first renders, and then using React hooks, useState() and useEffect() to change the color when the state of likes changes. However, I have got the color to render, but it is also rendering on load so not changing from black to green when a user clicks "like" and changes the like state.
import React, { useState, useEffect } from "react";
function Update() {
**const [like, updateLikes] = useState(0);
const [dislike, updateDislikes] = useState(0);
const [likeColor, setLikeColor] = useState("black");
const [dislikeColor, setDislikeColor] = useState("black");
useEffect(() => {
setLikeColor("green");
}, [like]);
useEffect(() => {
setDislikeColor("red");
}, [dislike]);**
return (
<div className="updateDiv">
<span className="update">
<img className="profilePic" src="https://picsum.photos/50/50" alt="" />
<div className="name">Username</div>
<div className="time">08:30am</div>
<div className="text">Reading a good book!</div>
<div className="likes">
Likes:
**<p style={{ color: likeColor }}>{like}</p>**
</div>
<div className="dislikes">
Dislikes:
<p style={{ color: dislikeColor }}>{dislike}</p>
</div>
<button type="submit" onClick={() => updateLikes(like + 1)}>
Like
</button>
<button type="submit" onClick={() => updateDislikes(dislike + 1)}>
Dislike
</button>
<hr />
</span>
</div>
);
}
export default Update;
So, I want the initial color of the like <p> element to be black when the page is first rendered, and then the useEffect methods to be called to change the color of said element when the state of "like" changes, but at the moment the color is being set when the page renders, so it isn't being initialised as black.
Probably a quick fix, but I'm starting to bang my head against the wall :D
The useEffect hook will also run on mount. So you need to prevent the hook from setting the color on the first render.
You can do this by using useRef hook.
const mountRef = useRef(false);
useEffect(() => {
if (mountRef.current) {
setLikeColor("green");
}
else {
mountRef.current = true;
}
}, like);
Because Your are calling setLikeColor and setDislikeColor under useEffect hook and initially useEffect is running and change the color.You can do like below :
import React, { useState, useEffect } from "react";
function Update() {
const [like, updateLikes] = useState(0);
const [dislike, updateDislikes] = useState(0);
const [likeColor, setLikeColor] = useState("black");
const [dislikeColor, setDislikeColor] = useState("black");
useEffect(() => {
console.log("useEffect");
if (like > 0) {
setLikeColor("green");
}
}, [like]);
useEffect(() => {
if (dislike > 0) {
setDislikeColor("red");
}
}, [dislike]);
return (
<div className="updateDiv">
<span className="update">
<img className="profilePic" src="https://picsum.photos/50/50" alt="" />
<div className="name">Username</div>
<div className="time">08:30am</div>
<div className="text">Reading a good book!</div>
<div className="likes">
Likes:<p style={{ color: likeColor }}>{like}</p>
</div>
<div className="dislikes">
Dislikes:
<p style={{ color: dislikeColor }}>{dislike}</p>
</div>
<button type="submit" onClick={() => updateLikes(like + 1)}>
Like
</button>
<button type="submit" onClick={() => updateDislikes(dislike + 1)}>
Dislike
</button>
<hr />
</span>
</div>
);
}
export default Update;
In my app.js for the button component I gave this props propTwo={"two"}
but still Button.js nothing is printing inside componentWillReceiveProps
can yoi tell me how to recieve the props using componentWillReceiveProps method
can you tell me how to use componentWillReceiveProps in my application
providing my code snippet and sandbox below
https://codesandbox.io/s/hopeful-villani-xyikq
class Button extends Component {
componentWillReceiveProps(nextprops) {
console.log("componentWillReceiveProps nextprops--->", nextprops);
}
render() {
return (
<div>
<button
onClick={() => {
// getPosts(channel);
// getAlert();
}}
className="btn btn-primary btn-lg btn-block"
>
Get top news
</button>
</div>
);
}
}
App.js
const App = () => (
<div>
<RecentChannelItem />
<ChannelsField propOne={"one"} />
<Button propTwo={"two"} />
<TopNews />
</div>
);
componentWillReceiveProps is already deprecated.
You can use componentDidUpdate.
You can access the updated props by accessing this.props inside the componentDidUpdate.
You should use:
static getDerivedStateFromProps(nextprops) {
console.log("componentWillReceiveProps nextprops--->", nextprops);
}