In a weather application on which I'm working I have three components, one App.js component which holds the other two components (search.js and Main.js). User searches the city, and main.js components display the relevant weather data.
Now I want to change the background dynamically for the full screen but for that, I need to access the API-data function in my App.js component, which will provide the icon id then I can change the background, but I am confused now about how to do? I have attached the code below.
Component App.js
import React, { useState } from "react";
import "./App.css";
import Maindata from "./Components/Maindata";
import Search from "./Components/Search";
function App() {
const [location, setLocation] = useState();
return (
<div className="mainpage"
style={{
backgroundImage: `url("./pics/01n.jpg")`,
backgroundSize: "cover",
}}
>
<div className="searchComp">
<Search {...{ location, setLocation }} />
</div>
<Maindata city={location} />
</div>
);
}
export default App;
Search.js
import React, { useState } from "react";
import "../Componentstyle/search.css";
export default function Search({ setLocation }) {
const [city, setCity] = useState("");
const handlesubmit = (e) => {
e.preventDefault();
setLocation(city );
};
return (
<div className="main">
<nav className="istclass">
<form className="form" onSubmit={handlesubmit}>
<div className="search">
<input
value={city}
placeholder="Search your location..."
className="searchbox"
onChange={(e) => setCity(e.target.value)}
/>
<button className="nd" type="button" onClick={handlesubmit}>
<i class="fa fa-search" aria-hidden="true"></i>
</button>
</div>
</form>
</nav>
</div>
);
}
Main. jsx
import React, { useState, useEffect } from "react";
// import Time from "./Time";
import moment from "moment";
import "../Componentstyle/Main.css";
export default function Maindata({ city = "mansehra" }) {
const [data, setData] = useState();
const [cityvalid, setCityvalid] = useState(false);
const Dweather = async (city) => {
const key = "24f4cabc9b1a10af6e3eeb4cc150a9ef";
await fetch(
`https://api.openweathermap.org/data/2.5/forecast?q=${city}&appid=${key}&units=metric&formatted=0`
)
.then((response) => response.json())
.then((actualData) => {
if (actualData.city) {
setCityvalid(true);
setData(actualData);
} else {
setCityvalid(false);
}
});
};
useEffect(() => {
Dweather(city);
}, [city]);
if (!data) {
return <div>Loading...</div>;
}
// if (!data.weather) {
// return <div>City "{city}" not recognized</div>;
// }
const icons = `./icons/${data.list[0].weather[0].icon}.svg`;
const icond1 = `./icons/${data.list[7].weather[0].icon}.svg`;
const icond2 = `./icons/${data.list[15].weather[0].icon}.svg`;
const icond3 = `./icons/${data.list[23].weather[0].icon}.svg`;
const icond4 = `./icons/${data.list[31].weather[0].icon}.svg`;
const icond5 = `./icons/${data.list[39].weather[0].icon}.svg`;
const sunrise = data.city.sunrise;
const sunset = data.city.sunset;
const timezone = data.city.timezone;
return (
<>
<div
className="newpage"
style={{
// backgroundImage: `url("./pics/${data.list[0].weather[0].icon}.jpg")`,
// backgroundSize: "cover",
flexWrap: "wrap",
padding: "1% 10% 0 10%",
height: "53rem",
}}
>
<div className="city">
<span className="name">{data.city.name}</span>
<br />
<span className="citydate">
{moment
.utc(new Date().setTime(data.list[0].dt * 1000))
.add(timezone, "seconds")
.format("dddd, MMMM Do YYYY, ")}
</span>
</div>
<div className="maindata">
{/* {!cityValid && <span>City "{city}" not found</span>} */}
<div className="temper">
<img src={icons} alt="not found" />
<div className="temp">
<span className="display">
{" "}
{data.list[0].main.temp.toFixed(1)}°
</span>{" "}
<br />{" "}
<span className="display1">
{" "}
{data.list[0].weather[0].description}
</span>
</div>
</div>
<div className="icon">
{/* <img src={link} alt="not found" />{" "} */}
<div className="acloudy">
<span className="icon1">
{data.list[0].main.temp_max.toFixed(1)} C°
</span>{" "}
<br /> <span className="icon2">High </span>
</div>
<div className="bcloudy">
<span className="icon1">
{" "}
{data.list[0].wind.speed.toFixed()} Km/h
</span>{" "}
<br /> <span className="icon2">Wind Speed</span>
</div>
<div className="ccloudy">
<span className="icon1">
{moment
.utc(sunrise, "X")
.add(timezone, "seconds")
.format("h:mm a")}{" "}
</span>
<br />
<span className="icon2">Sunrise</span>
</div>
<div className="dcloudy">
<span className="icon1">
{data.list[0].main.temp_min.toFixed(1)} C°
</span>{" "}
<br /> <span className="icon2">Low</span>
</div>
<div className="ecloudy">
<span className="icon1">{data.list[0].main.humidity}%</span>{" "}
<br /> <span className="icon2">Humadity</span>
</div>
<div className="fcloudy">
<span className="icon1">
{moment
.utc(sunset, "X")
.add(timezone, "seconds")
.format("h:mm a")}{" "}
</span>
<br /> <span className="icon2">Sunset</span>
</div>
</div>
</div>
<div className="dailyweather">
<div className="day">
<span className="wday">
{moment(new Date().setTime(data.list[7].dt * 1000)).format("ddd")}
</span>
<br /> <img src={icond1} alt="not found" />
<br />
<span className="head">Temp </span>{" "}
<span className="val">
{data.list[7].main.temp.toFixed(1)} C°
</span>{" "}
<br />
<br />
<span className="head">Feel like </span>{" "}
<span className="val">
{data.list[7].main.feels_like.toFixed(1)} C°
</span>{" "}
<br />
<br />
<span className="head">Moist </span>{" "}
<span className="val">
{data.list[7].main.humidity.toFixed()} %
</span>{" "}
<br />
<br />
<span className="head">{data.list[7].weather[0].main}</span>
</div>
<div className="day">
<span className="wday">
{moment(new Date().setTime(data.list[15].dt * 1000)).format(
"ddd"
)}
</span>{" "}
<br />
<img src={icond2} alt="not found" />
<br /> <span className="head">Temp </span>{" "}
<span className="val">
{data.list[15].main.temp.toFixed(1)} C°
</span>{" "}
<br />
<br />
<span className="head">Feel like </span>{" "}
<span className="val">
{data.list[15].main.feels_like.toFixed(1)} C°
</span>{" "}
<br />
<br />
<span className="head">Moist</span>{" "}
<span className="val">
{" "}
{data.list[15].main.humidity.toFixed()} %
</span>{" "}
<br />
<br />
<span className="head">{data.list[15].weather[0].main}</span>
</div>
<div className="day">
<span className="wday">
{moment(new Date().setTime(data.list[23].dt * 1000)).format(
"ddd"
)}
</span>
<br /> <img src={icond3} alt="not found" />
<br /> <span className="head">Temp</span>{" "}
<span className="val">
{" "}
{data.list[23].main.temp.toFixed(1)} C°
</span>
<br /> <br />
<span className="head">Feel like </span>{" "}
<span className="val">
{data.list[23].main.feels_like.toFixed(1)} C°
</span>{" "}
<br />
<br />
<span className="head">Moist </span>{" "}
<span className="val">
{data.list[23].main.humidity.toFixed()} %
</span>{" "}
<br />
<br />
<span className="head">{data.list[23].weather[0].main}</span>
</div>
<div className="day">
<span className="wday">
{moment(new Date().setTime(data.list[31].dt * 1000)).format(
"ddd"
)}
</span>{" "}
<br /> <img src={icond4} alt="not found" />
<br /> <span className="head">Temp</span>{" "}
<span className="val">
{" "}
{data.list[31].main.temp.toFixed(1)} C°
</span>
<br /> <br />
<span className="head">Feel like </span>{" "}
<span className="val">
{data.list[31].main.feels_like.toFixed(1)} C°
</span>{" "}
<br />
<br />
<span className="head">Moist </span>{" "}
<span className="val">
{data.list[31].main.humidity.toFixed()} %
</span>{" "}
<br />
<br />
<span className="head">{data.list[31].weather[0].main}</span>
</div>
<div className="day">
<span className="wday">
{moment(new Date().setTime(data.list[39].dt * 1000)).format(
"ddd"
)}
</span>
<br />
<img src={icond5} alt="not found" />
<br /> <span className="head">Temp </span>{" "}
<span className="val">
{data.list[39].main.temp.toFixed(1)} C°
</span>{" "}
<br />
<br />
<span className="head">Feel like </span>{" "}
<span className="val">
{data.list[39].main.feels_like.toFixed(1)} C°
</span>{" "}
<br />
<br />
<span className="head">Moist </span>{" "}
<span className="val">
{data.list[39].main.humidity.toFixed()} %
</span>{" "}
<br />
<br />
<span className="head">{data.list[39].weather[0].main}</span>
</div>
</div>
</div>
</>
);
}
React is designed in a way that data flows top to bottom. A component can get data as props from its parent, not the other way around. Still, you could update a state in the parent component by passing a state updater to the child.
You could pass a setBackgroundImageURL from App to Maindata to set the image you get from the API and have it available in App, by doing something like so:
function App() {
const [location, setLocation] = useState();
const [backgroundImageURL, setBackgroundImageURL] = useState("/pics/01n.jpg");
return (
<div
className="mainpage"
style={{
backgroundImage: `url(${backgroundImageURL})`,
backgroundSize: "cover",
}}
>
<div className="searchComp">
<Search {...{ location, setLocation }} />
</div>
<Maindata city={location} setBackgroundImageURL={setBackgroundImageURL} />
</div>
);
}
export default App;
export default function Maindata({ city = "mansehra", setBackgroundImageURL }) {
//....
const icons = `/icons/${data.list[0].weather[0].icon}.svg`;
setBackgroundImageURL(icons);
//....
Besides that, if you are having a problem with displaying the image, maybe you are not using the correct path. The answer to this question would help in which case.
You could use a global state management tool. React comes with useContext but if you’re looking for a more robust solution, you could look into redux in combination with react-redux. Then anywhere you need the data in the application you just use useDispatch
best solution to hit the ground running is to use React's built-in useContext hook.
Then, as the app grows, you could pivot to something like Jotai
Related
I've made a react mini project about creating a nft with a form attached when the form gets approved a mini pop up occurs for approval , minting , sign and lock.
The pop up doesnt appear don't know why or where am i mistaken. can anyone help me with this , greatly appreciated!
Here's my code so far for this stuff as of this moment when i click on create console.log doesn't print
const [showmodal, setshowmodal] = useState(false);
const [showbid, setShowbid] = useState(false);
const [accounts, setaccount] = useState("");
const handleFormSubmit = async (e) => {
e.preventDefault();
console.log("form submit")
setaccount(address); //
if (validateSingle()) { // validateSingle is form verification about fields
setShowbid(true);
}
<form onSubmit={handleFormSubmit} id="form-create-item" className="form-border" encType="multipart/form-data">
<div className="field-set">
<h5>Upload file</h5>
<div className="d-create-file">
<p id="file_name">PNG, JPG, GIF, WEBP or MP4. Max 200mb.</p>
{files.map(x =>
<p key="{index}">PNG, JPG, GIF, WEBP or MP4. Max 200mb.{x.name}</p>
)}
<div className='browse'>
<input type="button" id="get_file" className="btn-main" value="Browse"/>
<input id='upload_file' type="file" className="inputfile inputfile-1" data-multiple-caption="{count} files selected" multiple onChange={handleFile} />
</div>
</div>
<div className="row" style={{paddingTop:30}}>
<div md={8} sm={8} xs={8}>
<label>Put</label>
<p className="para-color">
Receive Bid
</p>
</div>
<div md={4} sm={4} xs={4} className="text-right">
<Toggle
onClick={onToggle}
on={<h2>On</h2>}
off={<h2>Off</h2>}
size="xs"
offstyle="danger"
active={toggleActive}
/>
</div>
{toggleActive === true ? (
<div className="form-row">
<div className="form-group col-md-6">
<div className="d-flex justify-content-between align-items-start">
<span
type="button"
className={
fixed === 1
? "nft_create_btn active"
: "nft_create_btn"
}
onClick={Onfixed}
>
Fixed Price
</span>
<span
type="button"
className={
timed === 1
? "nft_create_btn active"
: "nft_create_btn"
}
onClick={Ontimed}
>
Timed Price
</span>
<span
type="button"
className={
ongoing === 1
? "nft_create_btn active"
: "nft_create_btn"
}
onClick={Auctiongoing}
>
Ongoing Auction
</span>
</div>
</div>
</div>
) : (
""
)}
</div>
<div className="row" style={{paddingTop:30}}>
<span md={8} sm={8} xs={8}>
<label>Unlock Once</label>
<p className="para-color">
Content Unlock
</p>
</span>
<span md={4} sm={4} xs={4} className="text-right">
<Toggle
onClick={onToggle2}
on={<h2>On</h2>}
off={<h2>Off</h2>}
size="xs"
offstyle="danger"
active={toggleActive2}
/>
</span>
</div>
{toggleActive2 === true && (
<div className="mb-15" style={{paddingTop:15}}>
<div md={12}>
<div className="form-group">
<input
type="text"
className="form-control primary_inp"
id="digitalkey"
name="digitalkey"
onChange={onChangeunlock}
placeholder="Digital key,code to redeem or link to a file"
/>
<span>Tip: Markdown syntax is supported</span>
</div>
</div>
</div>
)}
{toggleActive === true && fixed === 1 && (
<div className="mb-15">
<div md={12}>
<div className="form-group">
{symbol == 'ETH' ? (
<label htmlFor="price" style={{color : "white"}}>
Instant Price{" "} ({symbol})
</label>
) : (
<label htmlFor="price" style={{color : "white"}}>
Instant Price{" "} ({symbol})
</label>
)}
<input
type="text"
className="form-control input-custom"
onChange={onChangeprice}
id="price"
name="price"
value={onchangeprice}
/>
</div>
</div>
</div>
)}
{toggleActive1 === true && timed === 1 && (
<div className="form-row">
<div className="form-group col-md-12">
<label className="primary_label" htmlFor="desccription">
Date{" "}
<span className="text-muted"></span>
</label>
<div className="d-flex">
<DatePicker
className="form-control input-custom"
selected={startDate}
onChange={(date) => setStartDate(date)}
selectsStart
startDate={startDate}
endDate={endDate}
dateFormat="dd/MM/yyyy h:mm aa"
showTimeInput
/>
<DatePicker
className="form-control input-custom"
selected={endDate}
onChange={(date) => setEndDate(date)}
selectsEnd
startDate={startDate}
endDate={endDate}
minDate={startDate}
dateFormat="dd/MM/yyyy h:mm aa"
showTimeInput
/>
</div>
</div>
<div className="form-group col-md-12">
<label className="primary_label" htmlFor="name">
Minimum Bid
</label>
<div className="input_group">
<input
type="text"
className="form-control input-custom"
onChange={onChangebid}
id="minimumbid"
name="minimumbid"
placeholder="Minimum Bid"
/>
</div>
</div>
</div>
)}
<div className="spacer-single"></div>
<h5>Title</h5>
<input type="text" name="item_title" id="name" className="form-control" placeholder="e.g. 'Crypto Funk" onChange={onChange}/>
<div className="spacer-10"></div>
<h5>Description</h5>
<textarea data-autoresize name="item_desc" id="description" className="form-control" placeholder="e.g. 'This is very limited item'" onChange={onChangeDescription}></textarea>
<div className="spacer-10"></div>
<div className="mb-15">
<div md={12}>
<div className="form-group">
<label htmlFor="category" style={{color:"white"}}>
Category
</label>
<Select
className=""
id="tokenCategory"
onChange={HandleChange}
options={CategoryOption}
/>
</div>
</div>
</div>
{/* <h5>Price in {symbol}</h5>
<input type="text" name="item_price" id="item_price" className="form-control" /> */}
<div className="spacer-10"></div>
<h5>Royalties</h5>
<input type="text" name="item_royalties" id="royalties" className="form-control" placeholder="suggested: 0, 10%, 20%, 30%. Maximum is 70%" onChange={onChangeroy}/>
<div className="spacer-10"></div>
<input type="button" id="submit" value="Create Item" className="connect-wallet create-item btn-main"/>
</div>
</form>
//Modal pop up
<Modal
show={showbid}
size="md"
backdrop="static"
onHide={handleClosebid}
centered
id="follow-steps-modal"
className="custom-style-modal"
>
<Modal.Header closeButton>
<Modal.Title>{language[localStorageLang].FOLLOW_STEPS}</Modal.Title>
</Modal.Header>
<Modal.Body className="pl-30 pr-30">
<Row>
<Col sm={2} md={2} className="col-xs-2">
{approveprograss === false ? (
<div className="follow-step-1-icon">
<i className="fa fa-check-circle"></i>
</div>
) : (
<div className="follow-step-2-icon">
<div className="loader"></div>
</div>
)}
</Col>
<Col sm={6} md={6} className="col-xs-10">
<div className="follow-step-1-content">
<h4>{language[localStorageLang].APPROVE}</h4>
<p className="para-color">
{language[localStorageLang].CHECKING_BALANCE}
</p>
</div>
</Col>
<Col sm={4} md={4} className="col-xs-12">
{approveprograss === false ? (
<div>
{approvesuccess === false ? (
<div className="follow-step-1-button">
<Link to="#" onClick={approve} disabled>
{language[localStorageLang].TRY_AGAIN}
</Link>
</div>
) : (
<div>
{approvesuccess === true ? (
<div className="follow-step-1-button">
<Link to="#" disabled>
{language[localStorageLang].DONE}
</Link>
</div>
) : (
<div className="follow-step-1-button">
<Link to="#" onClick={approve} className="">
{language[localStorageLang].START}
</Link>
</div>
)}
</div>
)}
</div>
) : (
<div className="follow-step-2-button">
<Link to="#" className="">
{language[localStorageLang].INPROGRESS}
</Link>
</div>
)}
</Col>
</Row>
<Row>
<Col sm={12} md={12}>
<hr />
</Col>
</Row>
<Row>
<Col sm={2} md={2} className="col-xs-2">
{uploadprograss === false ? (
<div className="follow-step-1-icon">
<i className="fa fa-check-circle"></i>
</div>
) : (
<div className="follow-step-2-icon">
<div className="loader"></div>
</div>
)}
</Col>
<Col sm={6} md={6} className="col-xs-10">
<div className="follow-step-2-content">
<h4>{language[localStorageLang].UPLOAD}</h4>
<p className="para-color">
{language[localStorageLang].CHECKING_BALANCE}
</p>
</div>
</Col>
<Col sm={4} md={4} className="col-xs-12">
{uploadprograss === false ? (
<div>
{uploadsuccess === false ? (
<div className="follow-step-1-button">
<Link to="#" onClick={mintCalling} disabled>
{language[localStorageLang].TRY_AGAIN}
</Link>
</div>
) : (
<div>
{uploadsuccess === true ? (
<div className="follow-step-1-button">
<Link to="#" disabled>
{language[localStorageLang].DONE}
</Link>
</div>
) : (
<div className="follow-step-1-button">
<Link to="#" onClick={mintCalling}>
{language[localStorageLang].START}
</Link>
</div>
)}
</div>
)}
</div>
) : (
<div className="follow-step-2-button">
<Link to="#" className="">
{language[localStorageLang].INPROGRESS}
</Link>
</div>
)}
</Col>
</Row>
<Row>
<Col sm={12} md={12}>
<hr />
</Col>
</Row>
<Row>
<Col sm={2} md={2} className="col-xs-2">
{sellprograss === false ? (
<div className="follow-step-1-icon">
<i className="fa fa-check-circle"></i>
</div>
) : (
<div className="follow-step-2-icon">
<div className="loader"></div>
</div>
)}
</Col>
<Col sm={6} md={6} className="col-xs-10">
<div className="follow-step-3-content">
<h4>Sign sell order</h4>
<p className="para-color">
{language[localStorageLang].CREATE_SIGNATURE}
</p>
</div>
</Col>
<Col sm={4} md={4} className="col-xs-12">
{sellprograss === false ? (
<div>
{sellsuccess === false ? (
<div className="follow-step-1-button">
<Link to="#" onClick={signsell} disabled>
{language[localStorageLang].TRY_AGAIN}
</Link>
</div>
) : (
<div>
{sellsuccess === true ? (
<div className="follow-step-1-button">
<Link to="#" disabled>
Done
</Link>
</div>
) : (
<div className="follow-step-1-button">
<Link to="#" onClick={signsell}>
{language[localStorageLang].START}
</Link>
</div>
)}
</div>
)}
</div>
) : (
<div className="follow-step-2-button">
<Link to="#" className="">
{language[localStorageLang].INPROGRESS}
</Link>
</div>
)}
</Col>
</Row>
<Row>
<Col sm={12} md={12}>
<hr />
</Col>
</Row>
<Row>
<Col sm={2} md={2} className="col-xs-2">
{lockprograss === false ? (
<div className="follow-step-1-icon">
<i className="fa fa-check-circle"></i>
</div>
) : (
<div className="follow-step-2-icon">
<div className="loader"></div>
</div>
)}
</Col>
<Col sm={6} md={6} className="col-xs-10">
<div className="follow-step-3-content">
<h4>{language[localStorageLang].SIGN_LOCK_ORDER}</h4>
<p className="para-color">
{language[localStorageLang].SIGN_LOCK_WALLET}
</p>
</div>
</Col>
<Col sm={4} md={4} className="col-xs-12">
{lockprograss === false ? (
<div>
{locksuccess === false ? (
<div className="follow-step-1-button">
<Link to="#" onClick={signlock} disabled>
{language[localStorageLang].TRY_AGAIN}
</Link>
</div>
) : (
<div>
{locksuccess === true ? (
<div className="follow-step-1-button">
<Link to="#" disabled>
{language[localStorageLang].DONE}
</Link>
</div>
) : (
<div className="follow-step-1-button">
<Link to="#" onClick={signlock}>
{language[localStorageLang].START}
</Link>
</div>
)}
</div>
)}
</div>
) : (
<div className="follow-step-2-button">
<Link to="#" className="">
{language[localStorageLang].INPROGRESS}
</Link>
</div>
)}
</Col>
</Row>
</Modal.Body>
</Modal>
Let me know if anything else is required , was trying to resolve this since long time but unable to !
I create multiple step button with useState hook and it work fine. Now I trying pass value of inputs from step two of button to step three. There is a problem I can't pass props or state in my function and I have error that state or props is undefined. I try more and more but give nothing.
This is my code :
const ShowOrNot = () => {
const [showForm, setShowForm] = useState(false);
const [showPreview, setShowPreview] = useState(false);
const [formHidden, setFormHidden] = useState(false);
return (
<div className="col-12">
{!showForm ? (
<ShowFormButton onClick={() => setShowForm(true)}/>
) : undefined}
{showForm ? (
<div className={''} id="scrollbar-style">
<div>
<HideFormButton
onClick={() => {
setShowForm(false);
}}
/>
</div>
{!formHidden ? <MyForm/> : undefined}
{!showPreview ? (
<ShowPreviewButton
onClick={() => {
setShowPreview(true);
setFormHidden(true);
}}
/>
) : undefined}
{showPreview ? (
<div className={"preview-send-wrapper"}>
<div className={"preview-send-header"}>
<div className={"preview-send-header-icon"}>
</div>
<h2>
Preview
</h2>
</div>
<div className={"mt-5 preview-send-cover"}>
<img src={value of inputs} alt={"cover"}/>
</div>
<div className={" preview-send-video-poster"}>
<img src={value of inputs} alt={"cover"}/>
<h1 className={"mt-4"}>
{this.props.videoTitle} // one value of inputs get here
<span>{two value of inputs get here}</span>
</h1>
<h4 className={"mt-3"}>
{value of inputs}
</h4>
</div>
<div className={"preview-send-summary-video"}>
<p>
{value of inputs}
</p>
</div>
<Row>
<div className={"col-lg-8 col-12"}>
<button className={"send-video-btn-final"}>
Send
</button>
</div>
<div className={"col-lg-4 col-12"}>
<SendButton
onClick={() => {
setFormHidden(false);
setShowPreview(false);
setShowForm(true);
}}
/>
</div>
</Row>
</div>
) : undefined}
</div>
) : undefined}
</div>
);
};
function SendButton({onClick}) {
return (
<div>
<button className="edit-send-video-btn w-100" onClick={onClick}>
Edit
</button>
</div>
);
}
function ShowFormButton({onClick}) {
return (
<div>
<button className="upload-content-btn w-100" onClick={onClick}>
<span className="ml-2">
</span>new upload{' '}
</button>
</div>
);
}
function ShowPreviewButton({onClick}) {
return (
<div className={"row show-preview-button"}>
<div className="col-lg-8 col mt-3">
<button className="preview-send-data-btn" onClick={onClick}>
Preview
</button>
</div>
<div className="col-lg-4 col mt-3">
<button className="draft-send-data-btn">Draft</button>
</div>
</div>
);
}
function HideFormButton({onClick}) {
return (
<div className={'content-send-form-close-btn'}>
<button onClick={onClick} className={'close-modal-btn'}>
<span>Close</span>
</button>
</div>
);
}
class MyForm extends Component {
constructor(props) {
super(props);
this.state = {
videoTitle: "",
category: "",
summary: "",
videoText: "",
}
}
onChange = (e) => {
this.setState({
[e.target.name]: e.target.value,
});
};
render() {
return (
<div className={"content-send-form-wrapper"}>
<div className={'content-send-form-header'}>
<div className={'content-send-form-header-title'}>
</div>
</div>
<form className={'mt-3 content-send-form-data register-teacher-inputs-box '}>
<Row>
<div className={'col-lg-6 col-12 mt-4'}>
<label htmlFor={'name'} className={' text-right'}>
<span>*</span>
</label>
<input
type="text"
className="form-control"
placeholder={'Title'}
name={'videoTitle'}
required="true"
value={this.state.videoTitle}
onChange={this.onChange}
onBlur={(e) => (e.target.placeholder = 'Title')}
onFocus={(e) => (e.target.placeholder = '')}
/>
</div>
<div className={'col-lg-6 col-12 mt-4'}>
<label htmlFor={'country'} className={' text-right'}>
<span>*</span>
</label>
<input
type="text"
className="form-control"
placeholder={'category'}
name={'category'}
value={this.state.category}
onChange={this.onChange}
required="true"
onBlur={(e) => (e.target.placeholder = 'category')}
onFocus={(e) => (e.target.placeholder = '')}
/>
</div>
</Row>
<Row>
<div className="col-12 mt-3 video-upload-input-btn">
<VideoUpload/>
</div>
</Row>
<Row>
<div className="col-lg-6 col-12 mt-3">
<PosterUpload/>
</div>
<div className="col-lg-6 col-12 mt-3">
<CoverUpload/>
</div>
</Row>
</form>
</div>
);
}
}
I'm trying to create a pop up subscription box which closes whenever one clicks on the close button or clicks anywhere outside the pop up. I've created a modal component and a state showModal which is used to toggle the visibility of this Modal. I have tried to add setShowModal(false) to the outer div element but that just disables the whole modal. What can be done to close the modal whenever we click outside the modal. This is how my main page looks
const [showModal, setShowModal] = useState(false);
return (
<>
<div
className="homepage"
style={{
filter: showModal ? "blur(8px)" : "none",
minHeight:"80vh",
}}
>
<section
className="homepage-hero"
style={{ paddingBottom:"-2rem", minHeight:"100vh" }}
>
<div className="hero-body">
<div className="container">
<div className="columns">
<div className="column ">
<h1>
<span className="heading">
Finance <br />
Scheme
</span>
<br />
</h1>
<p>
Lorem Ipsum
</p>
<div className="is-hidden-tablet">
</div>
<div className="button-group">
<button
style={{
fontWeight: "600",
padding: "0.75em 1.9em",
borderRadius: "0px",
color: "white",
backgroundColor: "#24ca7a",
border: "1px solid #24ca7a",
cursor: "pointer",
}}
onClick={() => setShowModal(true)}
>
Download
</button>
</div>
</div>
</div>
</div>
</div>
</section>
</div>
{showModal && (
<Modal
modalId="signup-modal"
onClose={() => setShowModal(false)}
canDismiss={false}
modalWidth="70%"
style={{position:"fixed", top:"20", minHeight:"50vh"}}
>
<div className="contact-us" style={{ margin:"20px"}}>
<section className="contact-form" >
<div className="container">
<div className="columns is-8 ">
<div
className="column is-half-desktop is-full-mobile container-content"
style={{ boxShadow: "none" }}
>
{submitted ? (
<div className="success">
<img src={confirmedIllus} alt="" />
<h2>Your details have been submitted successfully!</h2>
</div>
) : (
<form onSubmit={handleOnSubmit} id="contact-form" >
<h1 className="heading" style={{ fontSize: "2rem" }}>
Your Details
</h1>
<br />
<div className="field">
<label className="label">Name</label>
<div className="control">
<input
className="input"
id="name"
value={name}
type="text"
placeholder="Your Full Name"
onChange={(e) => setName(e.target.value)}
required
/>
</div>
</div>
<div className="field">
<label className="label">Email</label>
<div className="control ">
<input
className={`input ${isDanger}`}
id="email"
value={email}
type="email"
onChange={handleOnChange}
placeholder="Your Email"
required
/>
{!validEmail && isDanger ? (
<span className="icon is-small is-right">
<i className="material-icons-round">warning</i>
</span>
) : (
" "
)}
</div>
{!validEmail && isDanger ? (
<p className="help is-danger">{emailMessage}</p>
) : (
""
)}
</div>
<div className="field is-grouped submit-button-group">
<div className="control">
<button
style={{
cursor: !validEmail ? "not-allowed" : "pointer",
}}
className="button submit-button"
id="submit-form"
>
Submit
</button>
</div>
</div>
</form>
)}
</div>
<div className="column is-half-desktop is-full-mobile " >
<img
src="/images/Ebook.svg"
className="is-hidden-mobile"
style={{ width: "70%", marginTop: "40%" }}
/>
<div className=" font-blue bottom-text">
Fill your details to download the free <b> Ebook </b>
</div>
</div>
</div>
</div>
</section>
</div>
</Modal>
)}
</>
);
You can use the useOnClickOutside hook. This hook allows you to detect clicks outside of a specified element.
You have to import the followings
Create a ref that we add to the element for which we want to detect outside clicks
const ref = useRef();
State for our modal
const [showModal, setShowModal] = useState(false);
Call hook passing in the ref and a function to call on outside click
useOnClickOutside(ref, () => setShowModal(false));
render here
return(...);
//Hook
import { useEffect } from 'react';
export default function useOnClickOutside(ref, handler) {
useEffect(
() => {
const listener = (event) => {
// Do nothing if clicking ref's element or descendent elements
if (!ref.current || ref.current.contains(event.target)) {
return;
}
handler(event);
};
document.addEventListener("mousedown", listener);
document.addEventListener("touchstart", listener);
return () => {
document.removeEventListener("mousedown", listener);
document.removeEventListener("touchstart", listener);
};
},
// Add ref and handler to effect dependencies
// It's worth noting that because the passed-in handler is a new ...
// ... function on every render that will cause this effect ...
// ... callback/cleanup to run every render. It's not a big deal ...
// ... but to optimize you can wrap handler in useCallback before ...
// ... passing it into this hook.
[ref, handler]
);
}
See related repl output here - https://spanishhotloaderprogram.thelovekesh.repl.co/
For this, you can give tabIndex=-1 to your modal div, and then you can use the onBlur event.
const [showModal, setShowModal] = useState(false);
return (
<>
<div
className="homepage"
style={{
filter: showModal ? "blur(8px)" : "none",
minHeight:"80vh",
}}
>
<section
className="homepage-hero"
style={{ paddingBottom:"-2rem", minHeight:"100vh" }}
>
<div className="hero-body">
<div className="container">
<div className="columns">
<div className="column ">
<h1>
<span className="heading">
Finance <br />
Scheme
</span>
<br />
</h1>
<p>
Lorem Ipsum
</p>
<div className="is-hidden-tablet">
</div>
<div className="button-group">
<button
style={{
fontWeight: "600",
padding: "0.75em 1.9em",
borderRadius: "0px",
color: "white",
backgroundColor: "#24ca7a",
border: "1px solid #24ca7a",
cursor: "pointer",
}}
onClick={() => setShowModal(true)}
>
Download
</button>
</div>
</div>
</div>
</div>
</div>
</section>
</div>
{showModal && (
<Modal
modalId="signup-modal"
onBlur={() => setShowModal(false)}
canDismiss={false}
modalWidth="70%"
style={{position:"fixed", top:"20", minHeight:"50vh"}}
tabIndex={-1}
>
<div className="contact-us" style={{ margin:"20px"}}>
<section className="contact-form" >
<div className="container">
<div className="columns is-8 ">
<div
className="column is-half-desktop is-full-mobile container-content"
style={{ boxShadow: "none" }}
>
{submitted ? (
<div className="success">
<img src={confirmedIllus} alt="" />
<h2>Your details have been submitted successfully!</h2>
</div>
) : (
<form onSubmit={handleOnSubmit} id="contact-form" >
<h1 className="heading" style={{ fontSize: "2rem" }}>
Your Details
</h1>
<br />
<div className="field">
<label className="label">Name</label>
<div className="control">
<input
className="input"
id="name"
value={name}
type="text"
placeholder="Your Full Name"
onChange={(e) => setName(e.target.value)}
required
/>
</div>
</div>
<div className="field">
<label className="label">Email</label>
<div className="control ">
<input
className={`input ${isDanger}`}
id="email"
value={email}
type="email"
onChange={handleOnChange}
placeholder="Your Email"
required
/>
{!validEmail && isDanger ? (
<span className="icon is-small is-right">
<i className="material-icons-round">warning</i>
</span>
) : (
" "
)}
</div>
{!validEmail && isDanger ? (
<p className="help is-danger">{emailMessage}</p>
) : (
""
)}
</div>
<div className="field is-grouped submit-button-group">
<div className="control">
<button
style={{
cursor: !validEmail ? "not-allowed" : "pointer",
}}
className="button submit-button"
id="submit-form"
>
Submit
</button>
</div>
</div>
</form>
)}
</div>
<div className="column is-half-desktop is-full-mobile " >
<img
src="/images/Ebook.svg"
className="is-hidden-mobile"
style={{ width: "70%", marginTop: "40%" }}
/>
<div className=" font-blue bottom-text">
Fill your details to download the free <b> Ebook </b>
</div>
</div>
</div>
</div>
</section>
</div>
</Modal>
)}
</>
);
In your div className homepage you can use a condition when you click, if showModal is true --> setShowModal to false like
<div
className="homepage"
style={{
filter: showModal ? "blur(8px)" : "none",
minHeight: "80vh",
}}
onClick={() => showModal && setShowModal(false)}
>
I have a login page and below shown the jsx of my login page .Login submit button is inside here.on clicking this login button nothin is triggered or no change reflected
const SectionLogin = ({ onLoginClick, setEmail, setPassword }) => {
return (
<>
<div
className='wrapper'
style={{
backgroundImage: 'url(' + require('app/assets/img/j.jpg') + ')',
}}
>
<Container>
<Row>
<Col
className='mx-auto'
lg='4'
md='6'
style={{ paddingTop: '60px' }}
>
<Card className='card-register' style={{ padding: '15px' }}>
<h3 className='title mx-auto'>Welcome</h3>
<div className='social-line text-center'>
<Button
className='btn-neutral btn-just-icon mt-0'
color='facebook'
// onClick={(e) => e.preventDefault()}
>
<i
className='fab fa-facebook fa-3x'
style={{ color: '#3b5998' }}
/>
</Button>
<Button
className='btn-neutral btn-just-icon mt-0 ml-1'
color='google'
// onClick={(e) => e.preventDefault()}
>
<i
className='fab fa-google-plus fa-3x'
style={{ color: '#db4a39' }}
/>
</Button>
<Button
className='btn-neutral btn-just-icon mt-0 ml-1'
color='twitter'
// onClick={(e) => e.preventDefault()}
>
<i
className='fab fa-twitter fa-3x'
style={{ color: '#00acee' }}
/>
</Button>
</div>
<Form className='register-form'>
<label>Email</label>
<InputGroup className='form-group-no-border'>
<InputGroupAddon addonType='prepend'>
<InputGroupText>
<i className='nc-icon nc-email-85' />
</InputGroupText>
</InputGroupAddon>
<Input
placeholder='Email'
type='email'
// onChange={(e) => setEmail(e.target.value)}
/>
</InputGroup>
<label>Password</label>
<InputGroup className='form-group-no-border'>
<InputGroupAddon addonType='prepend'>
<InputGroupText>
<i className='nc-icon nc-key-25' />
</InputGroupText>
</InputGroupAddon>
<Input
placeholder='Password'
type='password'
// onChange={(e) => setPassword(e.target.value)}
/>
</InputGroup>
<Button
block
className='btn-round'
color='warning'
type='button'
onClick={onLoginClick}
>
Login
</Button>
</Form>
<div className='forgot'>
<Button
className='btn-link'
color='secondary'
// onClick={(e) => e.preventDefault()}
>
Forgot password?
</Button>
</div>
</Card>
<div className='col text-center'>
{/* <Button
className='btn-round'
outline
color='neutral'
href='/register-page'
size='lg'
target='_blank'
>
View Register Page
</Button> */}
</div>
</Col>
</Row>
</Container>
</div>
</>
);
};
export default SectionLogin;
button code is inside this SectionLogin Container(inside return where my login page jsx reside)
import React, { useEffect, useCallback, useState } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import SectionLogin from './LoginPage';
const LoginContainer = () => {
const dispatch = useDispatch();
const onLoginClick = (e) => {
console.log('hereeee');
alert('Hello');
};
return (
<>
<div className='content'>
<SectionLogin
onLoginClick={onLoginClick}
/>
</div>
</>
);
};
export default LoginContainer;
onLoginClick function is not triggering when button is clicked.
Can you try this,
<Button
block
className="btn-round"
color="warning"
type="button"
onClick={(event)=>onLoginClick(event)}>
Login
</Button>;
Hope this helps!!
Pass your onClick function as onLoginClick
<div className='content'>
<SectionLogin
onLoginClick={onLoginClick}
/>
</div>
And use it as
<Button
block
className="btn-round"
color="warning"
type="button"
onClick={() => onLoginClick() }
>
Login
</Button>;
I am trying to initialize a form with some user information using Redux Forms by pulling the information from my components state. I have a redux action in the componentDidMount method of my component that calls the action, retrieves the information, and then maps a 'profile' object from my store to the components props. The problem is, when I go to setState to update the profile info, it comes back as undefined. I have tried to use the componentWillRecieveProps to see if I can catch the updated 'Profile' props but it is still undefined. Whats the best way to update the component's state once 'this.props.profile' returns the users information?
Here is the component's code:
import React, { Component } from "react";
import { connect } from "react-redux";
import { Field, reduxForm } from "redux-form";
import { Link } from "react-router-dom";
import classnames from "classnames";
import * as actions from "../../actions";
class CreateProfile extends Component {
constructor(props) {
super(props);
this.state = {
showSocialMedia: true,
profile: {}
};
}
componentDidMount() {
this.props.getCurrentUserProfile();
}
// componentDidUpdate(prevProps, prevState) {
// if (prevProps.profile.profile !== this.props.profile.profile) {
// console.log(this.props.profile);
// }
// }
renderField(field) {
return (
<div className="form-group">
<input
className={classnames("form-control form-control-lg", {
"is-invalid": field.meta.touched && !field.meta.valid
})}
type={field.type}
placeholder={field.placeholder}
{...field.input}
/>
<small className="text-muted">{field.description}</small>
<div className="invalid">
{field.meta.touched && !field.meta.valid ? (
<div className="text-center">
<i className="far fa-edit" /> {field.meta.error}
</div>
) : (
""
)}
</div>
</div>
);
}
renderAlert() {
if (this.props.errors.message) {
return (
<div className="alert alert-danger error-message mt-4 text-center">
<h3>
<i className="fas fa-info-circle" />
</h3>
<h6 className="invalid">{this.props.errors.message}</h6>
</div>
);
}
}
renderSelectField(field) {
return (
<div className="form-group">
<select
className={classnames("form-control form-control-lg", {
"is-invalid": field.meta.touched && !field.meta.valid
})}
{...field.input}
>
<option value="" disabled>
* Select a Professional Status
</option>
<option value="Developer">Developer</option>
<option value="Junior Developer">Junior Developer</option>
<option value="Senior Developer">Senior Developer</option>
<option value="Manager">Manager</option>
<option value="Student or Learning">Student or Learning</option>
<option value="Instructor or Teacher">Instructor or Teacher</option>
<option value="Intern">Intern</option>
<option value="Other">Other</option>
</select>
<small className="text-muted">
Give us an idea of where you are at in your career
</small>
<div className="invalid">
{field.meta.touched && !field.meta.valid ? (
<div className="text-center">
<i className="far fa-edit" /> {field.meta.error}
</div>
) : (
""
)}
</div>
</div>
);
}
renderSocialMediaField(field) {
return (
<div className="form-group">
<div className="input-group-prepend">
<span className="input-group-text">
<i className={field.icon} />
</span>
<input
type={field.type}
className="form-control"
placeholder={field.placeholder}
icon={field.icon}
{...field.input}
/>
</div>
</div>
);
}
onSubmit(values) {
this.props.createNewUserProfile(values);
}
toggleHiddenSocialInputs(e) {
e.preventDefault();
this.setState({
showSocialMedia: !this.state.showSocialMedia
});
}
render() {
const { handleSubmit } = this.props;
const { profile } = this.props;
return (
<div className="container">
<div className="row">
<div className="col-md-8 m-auto">
<Link to="/dashboard" className="btn btn-light p-2 mt-2">
<i className="mr-1 fas fa-long-arrow-alt-left" /> Go Back
</Link>
<h5 className="display-4 pt-2 text-center font-weight-light">
Update Your Profile
</h5>
<p className="text-black-50 pt-3 font-weight-light">
* = required field
</p>
<form onSubmit={handleSubmit(this.onSubmit.bind(this))}>
{this.renderAlert()}
<Field
name="handle"
type="text"
placeholder="* Profile handle"
component={this.renderField}
description="A unique handle for your profile URL - (Can't be changed later)"
/>
<Field name="status" component={this.renderSelectField} />
<Field
name="company"
type="text"
placeholder="Company"
component={this.renderField}
description="Can be your own or the one you work for"
/>
<Field
name="website"
type="text"
placeholder="Website"
component={this.renderField}
description="Could be your own or company website"
/>
<Field
name="location"
type="text"
placeholder="Location"
component={this.renderField}
description="Suggested format is: City, State"
/>
<Field
name="skills"
type="text"
placeholder=" Skills"
component={this.renderField}
description="Please use comma separated values (eg: HTML, CSS, Javascript, etc)"
/>
<Field
name="githubusername"
type="text"
placeholder="Github Username"
component={this.renderField}
description="If you want your latest repos and a Github link, include your username"
/>
<div className="form-control-group">
<Field
className="form-control form-control-lg"
name="bio"
placeholder="A short bio about yourself"
component="textarea"
/>
<small className="text-muted">
Tell us a little about yourself
</small>
</div>
<div className="row mt-2 pt-2">
<button
className="btn btn-outline-secondary m-auto"
onClick={this.toggleHiddenSocialInputs.bind(this)}
>
Add Social Network Links <i className=" ml-1 fas fa-users" />
</button>
</div>
{!this.state.showSocialMedia && (
<div className="mt-3">
<Field
name="facebook"
placeholder="Facebook profile URL"
icon="fab fa-facebook-square"
component={this.renderSocialMediaField}
/>
<Field
name="twitter"
placeholder="Twitter profile URL"
icon="fab fa-twitter-square"
component={this.renderSocialMediaField}
/>
<Field
name="linkedin"
placeholder="Linkedin profile URL"
icon="fab fa-linkedin"
component={this.renderSocialMediaField}
/>
<Field
name="youtube"
placeholder="Youtube profile URL"
icon="fab fa-youtube-square"
component={this.renderSocialMediaField}
/>
<Field
name="instagram"
placeholder="Instagram profile URL"
icon="fab fa-instagram"
component={this.renderSocialMediaField}
/>
</div>
)}
<button action="submit" className="btn btn-info btn-block mt-5">
Create Profile <i className=" ml-1 fas fa-user-alt" />
</button>
{this.renderAlert()}
</form>
</div>
</div>
</div>
);
}
}
function validate(values) {
const errors = {};
if (!values.handle) {
errors.handle = "Please enter a handle for your profile";
}
if (!values.status) {
errors.status = "Please select a status for your profile";
}
return errors;
}
const mapStateToProps = state => {
return {
errors: state.errors,
profile: state.profile
};
};
export default reduxForm({
validate,
form: "CreateProfile",
initialValues: {}
})(connect(mapStateToProps, actions)(CreateProfile));
First, I'm not sure why you want to attach profile to component state. But if this.props.profile is always undefined, then it sounds like you're failing to fetch the user profile or you're not updating the store correctly. I would need to see getCurrentUserProfile and your reducer.
Fwiw, I would dispatch a request for user information from a container and set initialValues to state.profile (if state.profile, is in fact, your initial user data).