React js auto refresh on accessing component - reactjs

This is Home
function Home(){
const [posts,setPosts] = useState([])
const [isLogged,setActive] = useState(false)
const history = useHistory()
function handleSubmit(e)
{
e.preventDefault()
history.push(`/${e.target.name}`)
}
function handleLogout(e){
e.preventDefault()
setActive(false)
cookies.remove('blog')
}
useEffect(async ()=> {
try{const res = await axios.get('/api/posts')
setPosts(res.data)
if(cookies.get('blog'))
setActive(true)
} catch(err){
console.log('internal error')
}
},[])
return (
<div>
<header className='h-head'>
<div className='h-head-internal'>
<h1 className='head-h1'>Travel Blog</h1>
{ isLogged ? null : <button className='head-btn' name='Signup' onClick={handleSubmit}>Sign-Up</button>}
{ isLogged ? null :<button className='head-btn' name='Signin' onClick={handleSubmit}>Sign-In</button>}
{ isLogged ? <button className='head-btn' name='Createpost' onClick={handleSubmit}>Create-Post</button> : null }
{ isLogged ? <button className='head-btn' name='Logout' onClick={handleLogout}>LogOut</button> : null }
</div>
</header>
<h1 className='post'>POSTS</h1>
<div className='container'>
{posts.map(post => {
return <Post title={post.title} author={post.author} description={post.description} image={post.image} />
})}
</div>
</div>
)
}
export default Home
On returning to home page signup and signin are to be replaced by logout and create post as cookies has been saved in browser but it is not detecting it unless I refresh the page so, what to do
function Signin(){
const [data, setData] = useState({
email:"",
password:""
})
const history = useHistory()
async function signinpost(){
const res = await axios.post('/api/signin',data)
if(!res)
return console.log(res)
console.log(res)
}
function Redirecthandler(e) {
e.preventDefault()
history.push('/Signup')
}
function handleChange(e){
const { name, value } = e.target
setData(prev => {
return {
...prev,
[name]:value
}
}) }
function handleSubmit(e){
e.preventDefault()
signinpost()
history.push('/')
}
return (
<React.Fragment>
<div className='main flex'>
<header className='head'>
<h1>Travel Blog</h1>
</header>
<form className='flex form-top-pad' method='post'>
<div>
<label className='label label-left-pad' for='email'>EMAIL :</label>
<input className='input' type='email' name='email' placeholder='Email' onChange={handleChange}/>
</div>
<div>
<label className='label' for='password'>PASSWORD :</label>
<input className='input' type='password' name='password' placeholder='Password' onChange={handleChange} />
</div>
<input className='btn' type='submit' value='SIGNIN' onClick={handleSubmit} />
<button className='under-btn' onClick={Redirecthandler}>
New User ? Get Started
</button>
</form>
</div>
</React.Fragment>
)
}
export default Signin
I am redirecting from signin page to home after setting cookies in browser but the signin and signup button are not getting disabled without refresh how can I trigger a auto refresh whenever the home component is accessed please help

Related

How do I send data to my backend by clicking on save the page with REACT

How is it possible to send these data (Taste, Trust, content of question all questions (which are in Tabs.jsx), everything except the description see the picture please) to my backend by clicking on 'Save the page'.In first part before putting any url inside, I really want to see the data in the console log for now I have nothing printed out except this message :
SyntheticBaseEvent {_reactName: "onClick", _targetInst: null, type: "click", nativeEvent: PointerEvent, target: HTMLButtonElement…}
I have 2 versions but I don't know the difference, what is better to use, I just saw these 2 ways in this forum.
export default function MenuItemDisplay() {
const [data, setData] = useState({
taste: "",
trust: ""
});
function onSubmit(e) {
e.preventDefault();
axios
.post("", {
trust: data.trust,
taste: data.taste
})
.then((res) => {
console.log(res.data);
});
}
function handleSubmit(e) {
const newData = { ...data };
newData[e.target.id] = e.target.value;
setData(newData);
console.log(e);
}
const onError = () => {
console.log("Error");
};
function Checkbox({ value }) {
const [checked, setChecked] = useState(true);
return (
<label>
<input
type="checkbox"
defaultChecked={checked}
onChange={() => setChecked(!checked)}
/>
{value}
</label>
);
}
return (
<>
<h1> {item.name} </h1>
<div>
<div className="TextStyle">
{"Taste "}
<Dropdown ... /> .
</div>
...
<Checkbox value={!!item.trust} />
</div>
...
<button
type="submit"
onClick= {handleSubmit}
> Save the content
</button>
</>
);
}
OR the same code with fetch :
export default function MenuItemDisplay() {
const [trust, setTrust] = useState("item.trust");
const [taste, setTaste] = useState("item.taste");
const [message, setMessage] = useState("");
let handle = async (e) => {
e.preventDefault();
try {
let res = await fetch("", {
method: "POST",
body: JSON.stringify({
trust: trust,
taste: taste
})
});
let resJson = await res.json();
if (res.status === 200) {
setTaste("");
setTrust("");
message("Success");
} else {
setMessage("Some error occured");
}
} catch (err) {
console.log(err);
}
};
return (
<>
<form onSubmit={hadle}>
<h1> {item.name} </h1>
<div>
<div className="TextStyle">
{"Taste "}
<Dropdown
style={styles.select}
options={TASTE}
defaultValue={TASTE.find((t) => t.label === item.taste)}
styleSelect={colourStyles}
isMulti={true}
/>
</div>
<div className="TextStyle">
{"Trust "}
<Checkbox value={!!item.trust} />
</div>
<div className="TextStyle"> Description : {item.description} </div>
<Tabs data={item.questions} />
</div>
<button>Save</button>
</form>
</>
);
}
Plus I have another form inside my MenuItemDisplay component that is Tabs.jsx. I really don't don't how can I deal with these 2 forms and how to 'trace' these data...
Here is my code
You can go with the following approaches.
Using a form element
You need to send the form data to the backend using AJAX calls. The most conventional way to do so is to use a JSX form element.
export default function MenuItemDisplay() {
...
return (
<form onSubmit={handleSubmit}>
<h1> {item.name} </h1>
<div>
<div className="TextStyle">
{"Taste "}
<Dropdown
style={styles.select}
options={TASTE}
defaultValue={TASTE.find((t) => t.label === item.taste)}
styleSelect={colourStyles}
isMulti={true}
/>
</div>
<div className="TextStyle">
{"Trust "}
<Checkbox value={!!item.trust} />
</div>
<div className="TextStyle"> Description : {item.description} </div>
<Tabs data={item.questions} />
</div>
<button type="submit"> Save the page</button>
</form>
);
}
Using a handleSubmit callback to the save button
Another way to do it using the button to send the request to the backend when clicked.
export default function MenuItemDisplay() {
...
return (
<>
<h1> {item.name} </h1>
<div>
<div className="TextStyle">
{"Taste "}
<Dropdown
style={styles.select}
options={TASTE}
defaultValue={TASTE.find((t) => t.label === item.taste)}
styleSelect={colourStyles}
isMulti={true}
/>
</div>
<div className="TextStyle">
{"Trust "}
<Checkbox value={!!item.trust} />
</div>
<div className="TextStyle"> Description : {item.description} </div>
<Tabs data={item.questions} />
</div>
<button onClick={handleSubmit}> Save the page</button>
</>
);
}
All you need to do is define the handleSubmit callback. If you use the form element, you'd need to prevent the default form submission behavior.
async function handleSubmit(e) {
e.preventDefault(); // if you use the form tag
// validate the data here
// use fetch or axios or any other 3rd party library to send data to the back end
// receive response from backend
// do something with the response
}

Why doesn't my React app redirect after login?

I'm new to React and Typescript and what I'm trying to do is, after successfully logging in I want to redirect the user to the homepage, but navigate doesn't seem to work.
Here is my login component:
function Login() {
const auth = useRecoilValue(authAtom);
const { register, handleSubmit, formState } = useForm<IFormValues>();
const navigate = useNavigate();
const { isSubmitting } = formState;
console.log(isSubmitting);
function onSubmit(values: IFormValues ) {
const baseUrl = `${process.env.REACT_APP_API_URL}/users/authenticate`;
const creds = {
Username: values.username,
Password: values.password
};
return authenticateApi(baseUrl, creds)
.then(X => {
navigate('/');
});
}
useEffect(() => {
// redirect to home if already logged in
if (auth) navigate('/');
}, []);
return (
<div className="col-md-6 offset-md-3 mt-5">
<div className="card">
<h4 className="card-header">Login</h4>
<div className="card-body">
<form onSubmit={handleSubmit(onSubmit)}>
<div className="form-group">
<label>Username</label>
<input type="text" {...register("username")} className={`form-control`} />
<div className="invalid-feedback"></div>
</div>
<div className="form-group">
<label>Password</label>
<input type="password" {...register("password")} className={`form-control`} />
<div className="invalid-feedback"></div>
</div>
<button disabled={isSubmitting} className="btn btn-primary">
{isSubmitting && <span className="spinner-border spinner-border-sm mr-1"></span>}
Login
</button>
</form>
</div>
</div>
</div>
)
}
I have been stuck on this for a while, so any help would be greatly appreciated.
Do you ever actually import useNavigate()? It comes from the react-router-dom package, and can be used like so:
import { useNavigate } from 'react-router-dom';
function Login() {
// ...
const navigate = useNavigate();
// ...
}
Try this one it might work! or you can create a new function to redirect user to homepage after login
import { useNavigate } from "react-router-dom";
function Login() {
//This is for navifating user to home page
const navigate = useNavigate();
const auth = useRecoilValue(authAtom);
const { register, handleSubmit, formState } = useForm<IFormValues>();
const { isSubmitting } = formState;
console.log(isSubmitting);
const onSubmit = (values: IFormValues ) => {
const baseUrl = `${process.env.REACT_APP_API_URL}/users/authenticate`;
const creds = {
Username: values.username,
Password: values.password
};
return authenticateApi(baseUrl, creds)
.then(X => {
navigate('/');
});
}
const auth = () => {
// redirect to home if already logged in
navigate('/');
};
return (
<div className="col-md-6 offset-md-3 mt-5">
<div className="card">
<h4 className="card-header">Login</h4>
<div className="card-body">
<form onSubmit={handleSubmit(onSubmit)}>
<div className="form-group">
<label>Username</label>
<input type="text" {...register("username")} className={`form-control`} />
<div className="invalid-feedback"></div>
</div>
<div className="form-group">
<label>Password</label>
<input type="password" {...register("password")} className={`form-control`} />
<div className="invalid-feedback"></div>
</div>
<button disabled={isSubmitting} className="btn btn-primary">
{isSubmitting && <span className="spinner-border spinner-border-sm mr-1"></span>}
Login
</button>
</form>
</div>
</div>
</div>
)
}

Trying to learn Reactjs by making a weather app but i'm stuck at "TypeError: Cannot read property 'temp' of undefined"

I'm very new to Reactjs and i try to learn by building something easy but i'm stuck at this error "TypeError: Cannot read property 'temp' of undefined" when i try to render the data fetched from openweathermap and i really don't know what i am doing wrong.
Any help please?
import React, {useState, useEffect} from "react"
import Weather from "./Weather"
import Loading from "./Loading"
const App = () =>{
const [data, setData] = useState([]);
const [text, setText] = useState("");
const [loading, setLoading] = useState(false);
const submitHandler = (e) =>{
e.preventDefault();
if(loading){
return <Loading />
}
}
const fetchWeather = async () =>{
try {
setLoading(true);
const response = await fetch(`https://api.openweathermap.org/data/2.5/weather?q=${text}&appid=4d8fb5b93d4af21d66a2948710284366&units=metric`);
const weather = await response.json();
setData(weather);
console.log(data);
setLoading(false);
} catch (error) {
console.log(error);
}
}
useEffect(() =>{
fetchWeather();
}, [text]);
return (
<section>
<form type="submit" className="form" onSubmit={submitHandler}>
<input type="text" value={text} onChange={(e) =>setText(e.target.value)} />
<button type="submit" className="btn">Search</button>
</form>
<Weather data={data} />
</section>
);
}
Weather component
import React from "react"
const Weather = ({data}) =>{
return (
<div>
{ (data !== "undefined") ? (
<section className="weather">
<div className="title">
<h2>{data.name}</h2>
</div>
<div className="today">
<div className="info">
<h3>{Math.floor(data.main.temp)} C</h3>
<p>{data.weather[0].description}</p>
</div>
<div className="icon">
</div>
</div>
</section>
) : ("")}
</div>
);
}
Try this way
<section>
<form type="submit" className="form" onSubmit={submitHandler}>
<input type="text" value={text} onChange={(e) => setText(e.target.value)} /> <button type="submit" className="btn">Search</button>
</form>
{data ? <Weather data={data} />: null}
</section>
);
Fixed by doing this in Weather component after some more google search.Thanks to all who responded and helped me with this.
Is this a good solution for future projects if i will have the same error?
import React from "react"
const Weather = ({data}) =>{
console.log(data);
return (
<div>
{(data.main && data.sys && data.weather) ? (
<section className="weather">
<div className="title">
<h2>{data.name}</h2>
</div>
<div className="today">
<div className="info">
<h3>{Math.floor(data.main.temp)} C</h3>
<p>{data.weather[0].description}</p>
</div>
<div className="icon">
</div>
</div>
</section>
) : null}
</div>
);
}

How to redirect and pass data as props on form submit in React?

I have a functional component as so:
const SearchForm = () => {
//stuffs
const handleSubmit = e => {
e.preventDefault();
fetchData();
return <Redirect to='/search' data={fetchedData} />
}
return (
<div>
<form onSubmit={ handleSubmit }>
<div className='input-field'>
<input placeholder="Search whatever you wish"
type="text"
value={keyword}
onChange={(e) => setKeyword(e.target.value)}
className='searchfield center-align white-text'
/>
</div>
</form>
</div>
)
}
export default SearchForm;
After the form is submitted, I want the page to be redirected to /search, and I want the fetchedData to be passed along with it. I tried using the Redirect component from react-router-dom but it doesn't seem to work. Any fix?
you can do from two ways
1.
const SearchForm = () => {
//stuffs
const [redirect, setRedirect] = useState(false);
const [data, setData] = useState();
const handleSubmit = e => {
e.preventDefault();
fetchData();
setRedirect(true);
setData(e);
}
if (redirect)
return <Redirect to={{ pathname: '/search', data: { data } }} />
return (
<div>
<form onSubmit={handleSubmit}>
<div className='input-field'>
<input placeholder="Search whatever you wish"
type="text"
value={keyword}
onChange={(e) => setKeyword(e.target.value)}
className='searchfield center-align white-text'
/>
</div>
</form>
</div>
)
}
export default SearchForm;
2.
const SearchForm = (props) => {
//stuffs
const [redirect, setRedirect] = useState(false);
const [data, setData] = useState();
const handleSubmit = e => {
e.preventDefault();
fetchData();
props.history.push({
pathname: '/search',
state:
{
//your data
}
})
}
return (
<div>
<form onSubmit={handleSubmit}>
<div className='input-field'>
<input placeholder="Search whatever you wish"
type="text"
value={keyword}
onChange={(e) => setKeyword(e.target.value)}
className='searchfield center-align white-text'
/>
</div>
</form>
</div>
)
}
export default SearchForm;
this is how to do it by passing state object in to prop:
<Redirect
to={{
pathname: "/search",
state: { data:fetchedData}
}}
/>
You can not use the <Redirect /> component in your fallback function because it's a component and can not be rendered there.
If you are using react-router-dom, you can easily use its hooks to redirect the user to another route. Using hooks are simpler and keeps your components easy to read.
Try this:
import { useHistory } from "react-router-dom";
const SearchForm = () => {
const { push } = useHistory();
//stuffs
const handleSubmit = e => {
e.preventDefault();
fetchData();
push({
pathname: '/search',
state: {
data: fetchedData
}
})
}
return (
<div>
<form onSubmit={handleSubmit}>
<div className='input-field'>
<input placeholder="Search whatever you wish"
type="text"
value={keyword}
onChange={(e) => setKeyword(e.target.value)}
className='searchfield center-align white-text'
/>
</div>
</form>
</div>
)
}

React: POST API call embedding wrong path

I created my project using CRA react CLI and I have stored data in a local JSON file in the public folder.
I have a Login Component. This is where I am making all the POST API calls using Axios and I've also have some other stuff. This component is later being imported inside Auth Layout.
The problem is: On submit, it is sending the POST request to the wrong path. It should send to /data/api/v1/login.json instead it is sending to http://localhost:3000/auth/data/api/v1/login.json.
I think this could be since the login component is loading from the auth layout. but, not sure how to resolve it.
Login component
import React, { useState, useEffect } from "react";
import { Link } from "react-router-dom";
//api calls
import axios from "axios";
import { setUserSession } from "../../Common/Utils/Common.js";
import { Button, Form, Input, InputGroup, InputGroupAddon } from "reactstrap";
const Login = (props) => {
const [loading, setLoading] = useState(false);
const username = useFormInput("");
const password = useFormInput("");
const [error, setError] = useState(null);
const handleLogin = () => {
setError(null);
setLoading(true);
axios
.post("data/api/v1/login.json", {
username: username.value,
password: password.value,
})
.then((response) => {
console.log("response", response);
setLoading(false);
setUserSession(response.data.token, response.data.user);
props.history.push("/admin/dashboard");
})
.catch((error) => {
setLoading(false);
if (error.response.status === 401)
setError(error.response.data.message);
else setError("Something went wrong. Please try again later.");
});
};
return (
<div className="container-fluid backgroundContainer">
<div className="Login">
<div className="login-form-container">
<div className="logo">
<img src={Logo} className="App-logo" alt="logo" />
</div>
<div className="content">
<Form className="login-form">
<h3 className="form-title">Welcome</h3>
<InputGroup>
<InputGroupAddon
className="input-group-addon"
addonType="prepend"
>
<i className="fa fa-user"></i>
</InputGroupAddon>
<Input
autoFocus
type="email"
aria-label="Username"
aria-describedby="username"
aria-invalid="false"
placeholder="Username or Email"
{...username}
/>
</InputGroup>
<InputGroup>
<InputGroupAddon
className="input-group-addon"
addonType="prepend"
>
<i className="fa fa-lock"></i>
</InputGroupAddon>
<Input
value={password}
placeholder="Password"
aria-label="password"
aria-describedby="password"
{...password}
// onChange={(e) => setPassword(e.target.value)}
type="password"
/>
</InputGroup>
<div className="form-actions">
{error && (
<>
<small style={{ color: "red" }}>{error}</small>
<br />
</>
)}
<br />
<button
className="pull-right"
block="true"
type="submit"
value={loading ? "Loading..." : "Login"}
onClick={handleLogin}
disabled={loading}
>
Login
</button>
<br />
</div>
<div className="forgotPassword">
<Link to="/auth/resetpassword">Forgot password?</Link>
</div>
</Form>
</div>
</div>
</div>
</div>
);
};
const useFormInput = (initialValue) => {
const [value, setValue] = useState(initialValue);
const handleChange = (e) => {
setValue(e.target.value);
};
return {
value,
onChange: handleChange,
};
};
export default Login;
Auth layout
import React from "react";
import Login from "../../components/pages/login/Login";
class Pages extends React.Component {
render() {
return (
<div className="wrapper wrapper-full-page" ref="fullPages">
<div className="full-page">
<Login {...this.props}></Login>
</div>
</div>
);
}
}
export default Pages;
Common.js this is a common service using in the login component.
// return the user data from the session storage
export const getUser = () => {
const userStr = sessionStorage.getItem('user');
if (userStr) return JSON.parse(userStr);
else return null;
}
// return the token from the session storage
export const getToken = () => {
return sessionStorage.getItem('token') || null;
}
// remove the token and user from the session storage
export const removeUserSession = () => {
sessionStorage.removeItem('token');
sessionStorage.removeItem('user');
}
// set the token and user from the session storage
export const setUserSession = (token, user) => {
sessionStorage.setItem('token', token);
sessionStorage.setItem('user', JSON.stringify(user));
}
You need the leading slash in your axios call, Change
axios.post("data/api/v1/login.json", {
username: username.value,
password: password.value,
})
to
axios.post("/data/api/v1/login.json", {
username: username.value,
password: password.value,
})
This will fix the problem with it adding the sub-path to your api call.

Resources