I'm very used to Rails but am adding React as a front-end for the first time and am hitting what I hope are very obvious beginner issues. I'm following this tutorial (roughly...with my own model structure), but it doesn't actually go over adding edit routes. (It's more CRD than CRUD for some reason...)
I have the following routes set up in my javascript/routes/index.jsx:
import React from "react";
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
import MainNavbar from "../components/MainNavbar";
import Home from "../components/Home";
import Topics from "../components/Topics";
import Topic from "../components/Topic";
import NewTopic from "../components/NewTopic";
export default (
<Router>
<MainNavbar />
<Routes>
<Route path="/" element={<Home />} />
<Route path="/topics" element={<Topics />} />
<Route path="/topic/:id" element={<Topic />} />
<Route path="/topic" element={<NewTopic />} />
</Routes>
</Router>
);
With this structure, it works perfectly fine. However, when I add a route for EditTopic it disappears from the page and a server error pops up:
19:50:16 js.1 | [watch] build started (change:
"app/javascript/routes/index.jsx") 19:50:16 js.1 | ✘ [ERROR] Could
not resolve "../components/EditTopic" 19:50:16 js.1 | 19:50:16 js.1
| app/javascript/routes/index.jsx:8:22: 19:50:16 js.1 | 8
│ import EditTopic from "../components/EditTopic";
The routes I am adding are pretty simple. I use:
import EditTopic from "../components/EditTopic";
And for the actual route I have tried both:
<Route path="/topics/:id" element={<EditTopic />} />
And:
<Route path="/topics/:id" element={<EditTopic />} />
Both create the same error. Can anyone help out as to where I'm going wrong?
EDIT
I've got an initial EditTopic.jsx set out based on the NewTopic.jsx that actually works. I know it's probably full of errors, but I was going to learn/debug using this as a template:
import React, { useState } from "react";
import { Link, useNavigate } from "react-router-dom";
const EditTopic = () => {
const navigate = useNavigate();
const [name, setName] = useState("");
const [definitions, setDefinitions] = useState("");
const [state_v_trait, setStateVTrait] = useState("");
const [measurement, setMeasurement] = useState("");
const [notes, setNotes] = useState("");
const stripHtmlEntities = (str) => {
return String(str)
.replace(/\n/g, "<br> <br>")
.replace(/</g, "<")
.replace(/>/g, ">");
};
const onChange = (event, setFunction) => {
setFunction(event.target.value);
};
const onSubmit = (event) => {
event.preventDefault();
const url = "/api/v1/topics/${this.state.id}";
if (name.length == 0 )
return;
const body = {
name: stripHtmlEntities(name),
definitions: stripHtmlEntities(definitions),
state_v_trait: stripHtmlEntities(state_v_trait),
measurement: stripHtmlEntities(measurement),
notes: stripHtmlEntities(notes)
};
const token = document.querySelector('meta[name="csrf-token"]').content;
fetch(url, {
method: "PUT",
headers: {
"X-CSRF-Token": token,
"Content-Type": "application/json",
},
body: JSON.stringify(body),
})
.then((response) => {
if (response.ok) {
return response.json();
}
throw new Error("Network response was not ok.");
})
.then((response) => navigate(`/topic/${response.id}`))
.catch((error) => console.log(error.message));
};
// CUE HTML
return (
<div className="container mt-5">
<div className="row">
<div className="col-sm-12 col-lg-6 offset-lg-3">
<h1 className="font-weight-normal mb-5">
Edit {name}.
</h1>
<form onSubmit={onSubmit}>
<div className="form-group">
<label htmlFor="topicName">Name</label>
<input
type="text"
name="name"
id="topicName"
className="form-control"
required
onChange={(event) => onChange(event, setName)}
/>
</div>
<div className="form-group">
<label htmlFor="topicDefinitions">Definitions</label>
<input
type="text"
name="definition"
id="topicDefinitions"
className="form-control"
onChange={(event) => onChange(event, setDefinitions)}
/>
</div>
<div className="form-group">
<label htmlFor="state_v_trait">State versus Trait</label>
<textarea
className="form-control"
id="state_v_trait"
name="state_v_trait"
rows="5"
onChange={(event) => onChange(event, setStateVTrait)}
/>
</div>
<div className="form-group">
<label htmlFor="measurement">How is this measured?</label>
<textarea
className="form-control"
id="measurement"
name="measurement"
rows="5"
onChange={(event) => onChange(event, setMeasurement)}
/>
</div>
<div className="form-group">
<label htmlFor="notes">Other Notes</label>
<textarea
className="form-control"
id="notes"
name="notes"
rows="5"
onChange={(event) => onChange(event, setNotes)}
/>
</div>
<button type="submit" className="btn custom-button mt-3">
Create Topic
</button>
<Link to="/topics" className="btn btn-link mt-3">
Back to topics
</Link>
</form>
</div>
</div>
</div>
);
// END HTML
};
export default NewTopic;
However, I have also tried it with this very stripped-down version of EditTopic.jsx and the error still persists:
import React, { useState } from "react";
import { Link, useNavigate } from "react-router-dom";
const EditTopic = () => {
};
export default NewTopic;
Your export has the wrong name.
export default NewTopic
should be
export default EditTopic
Related
I am making an app using react and ruby-on-rails. My issue is, when I use the commented out if statement (in App.js: line 31) everything works. However, when I try to use if statemen with expression (line 31), browser respond, that neither onLogin and onSignup is not a function.
App.js
import './App.css';
import HomePage from './HomePage'
import Feed from './Feed'
import Login from "./Login";
import Post from "./Post";
import Signup from './Signup';
import { Routes, Route } from "react-router-dom";
import { useState, useEffect } from 'react';
import NavBar from './NavBar';
import SearchUser from './SearchUser'
import UserPage from './UserPage'
function App() {
const [user, setUser] = useState(false) /* log in method */
const [search, setSearch] = useState([])
const [signup, setSignup] = useState(false)
useEffect(() => {
// auto-login
fetch("/me").then((r) => {
if (r.ok) {
r.json().then((user) => {
setUser(user)});
}
});
}, []);
if (!user) return(signup ? <Signup onSignup={setSignup}/> : <Login onLogin={setUser} onSignup={setSignup}/>);
// if (!user) return(<Login onLogin={setUser} />);
return (
<div className="App">
<NavBar user={user} onLogin={setUser} onSearch={setSearch} ></NavBar>
{search.length > 0 && <SearchUser users={search} clearSearch={setSearch}></SearchUser>}
<Routes>
<Route path="/feed" element={<Feed user={user}/>}></Route>
<Route path="/" element={<HomePage user={user} onLogin={setUser}/>}></Route>
<Route path="/signup" element={<Signup />}></Route>
<Route path="/login" element={<Login />}></Route>
<Route path="/posts/:id" element={<Post />}></Route>
<Route path="/users/:id" element={<UserPage userId={user.id} searched = {search} />}></Route>
</Routes>
</div>
);
}
export default App;
Login.js
import logo from './logo.svg';
import { useState } from 'react';
import { Link } from 'react-router-dom';
function Login({onLogin, onSignup}) {
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
const [errors, setErrors] = useState([])
function handleSubmit(e) {
e.preventDefault();
fetch("/login", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
username,
password,
}),
})
.then((r) => {
if(r.ok) {
setErrors([])
r.json().then((user) => {
onLogin(user)
console.log(`User: ${user.username} with id: ${user.id} has been logged in`)})
}
else {
r.json().then((err)=> setErrors(err.errors))
}
});
}
return(
<div className = "Login">
<header style={{display: "flex", flexDirection: "column", padding: "100px 500px"}}>
<section><img src={logo} style={{height: "50px", width: "50px"}} alt=""></img>Instaclone</section>
<form
onSubmit={handleSubmit}
style={{display: "flex", flexDirection: "column", margin: "50px 50px"}}>
{/* fetch error handlers for login and signup */}
{errors ?
<p>{errors}</p> :
<p></p>}
{/* fetch error handlers for login and signup */}
<label htmlFor="username">Username:</label>
<input
type="text"
id="username"
value={username}
onChange={(e) => setUsername(e.target.value)}>
</input>
<label htmlFor="password">Password:</label>
<input
type="password"
id="password"
value={password}
onChange={(e) => setPassword(e.target.value)}>
</input>
<button type='submit'>login</button>
<button onClick={()=>onSignup(true)}><Link to="/signup">Don't have an account?</Link></button>
</form>
</header>
</div>
);
}
export default Login;
Signup.js
import logo from './logo.svg';
import { useState } from 'react';
import { Link } from 'react-router-dom';
function Signup({onSignup}) {
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
const [passwordConfirmation, setPasswordConfirmation] = useState("");
const [errors, setErrors] = useState([])
function handleSubmit(e) {
e.preventDefault();
fetch("/signup", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
username,
password,
password_confirmation: passwordConfirmation,
}),
})
.then((r) => {
if(r.ok) {
r.json().then((user) => {
onSignup(false)
console.log(`User: ${user.username} has been created`)})
}
else {
r.json().then((err)=> setErrors(err.errors))
}
});
}
return(
<div className = "Signup">
<header style={{display: "flex", flexDirection: "column", padding: "100px 500px"}}>
<section><img src={logo} style={{height: "50px", width: "50px"}} alt=""></img>Instaclone</section>
<form
onSubmit={handleSubmit}
style={{display: "flex", flexDirection: "column", margin: "50px 50px"}}>
{/* fetch error handlers for login and signup */}
{errors.length > 0 ?
errors.map((error, index)=><p key={index}>{error}</p>) :
<p></p>}
{/* fetch error handlers for login and signup */}
<label htmlFor="username">Username:</label>
<input
type="text"
id="username"
value={username}
onChange={(e) => setUsername(e.target.value)}>
</input>
<label htmlFor="password">Password:</label>
<input
type="password"
id="password"
value={password}
onChange={(e) => setPassword(e.target.value)}>
</input>
<label htmlFor="password_confirmation">Confirm Password:</label>
<input
type="password"
id="password_confirmation"
value={passwordConfirmation}
onChange={(e) => setPasswordConfirmation(e.target.value)}>
</input>
<button type='submit'>Signup</button>
<button onClick={()=>onSignup(false)}><Link to="/login">I have an account!</Link></button>
</form>
</header>
</div>
);
}
export default Signup;
I think the problem is an expression that I used. However, I am not sure what might be the case as I am not getting any errors except the ones mentioned.
enter image description here
I tried to use the old statement I was using and surprisingly it works
I am making a Register and Login page. I can't get an answer from the page.I couldn't find the error even though I examined the POST method examples.
This is the whole code
import { useState } from 'react'
function App() {
const [name, setName] = useState('')
const [email, setEmail] = useState('')
const [password, setPassword] = useState('')
async function registerUser(event) {
event.preventDefault()
const response = await fetch('http://localhost:3000/api/register', {
method:"POST",
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
name,
email,
password,
}),
})
const data = await response.json()
if (data.status === 'ok') {
history.push('/login')
}
}
return (
<div>
<h1>Register</h1>
<form onSubmit={registerUser}>
<input
value={name}
onChange={(e) => setName(e.target.value)}
type="text"
placeholder="Name"
/>
<br />
<input
value={email}
onChange={(e) => setEmail(e.target.value)}
type="email"
placeholder="Email"
/>
<br />
<input
value={password}
onChange={(e) => setPassword(e.target.value)}
type="password"
placeholder="Password"
/>
<br />
<input type="submit" value="Register" />
</form>
</div>
)
}
export default App
The part of the site that gives an error
const response = await fetch('http://localhost:3000/api/register', {
method:"POST",
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
name,
email,
password,
}),
})
Register.js:14 POST http://localhost:3000/api/register 404 (Not Found)
This is the part where I use this function. I don't think a possible bug here will affect the POST method, but I'm sharing it anyway.
const express = require("express")
const app = express()
const cors = require("cors")
const mongoose = require("mongoose")
const User = require("./models/user.model")
mongoose.connect("mongodb://localhost:27017/test-db")
app.use(cors())
app.use(express.json())
app.post("/api/register",async(req,res)=>{
console.log(req.body)
try {
await User.create({
name:req.body.name,
email:req.body.email,
password:rawListeners.body.password
})
res.json({status:"ok"})
} catch (err) {
res.json({status:"error",error:"Duplicate email"})
}
})
app.post("/api/login",async(req,res)=>{
const user= await User.findOne({
email:req.body.email,
password:req.body.password
})
if(user){
return res.json({status:"ok", user:true})
}else{
return res.json({status:"error",user:false})
}
})
app.listen(3000,()=>{
console.log("Server started")
})
and
import React from 'react'
import { BrowserRouter, Route, Routes,Router } from 'react-router-dom'
import Login from './pages/Login'
import Register from './pages/Register'
const App = () => {
return (
<div>
<BrowserRouter>
<Routes>
<Route path="/login" element={<Login />} />
<Route path="/register" element={<Register />} />
</Routes>
</BrowserRouter>
</div>
)
}
export default App
Examined the post method, I guess there is a mistake. There is no problem with the port in the Fetch section.
Welcome to SO!
So I took a look at your code, and I think the problem might be here:
...
return (
<div>
<BrowserRouter>
<Routes>
<Route path="/login" element={<Login />} />
<Route path="/register" element={<Register />} />
</Routes>
</BrowserRouter>
</div>
)
....
The path for the registration page is /register, yet you're using /api/register elsewhere. This may give you the error, as it tries sending a POST request to a non-existent endpoint.
I am working on firebase authentication. I have made login, logout(on home), home pages. All are working fine. But when I try to login after I have changed something in router or in my code it works perfectly, that is redirects to Home. But when I login after logout, It does not work and reloads the same login page.
Also when isLoggedIn is set true after first try, it reloads login component. When I manually change url to /home then it works fine.
Here is my code.
App js
import Signup from "./Signup";
import Login from "./Login";
import { BrowserRouter, Routes, Route } from "react-router-dom";
import Home from "./Home";
import ProtectedRoutes from "../ProtectedRoutes";
export default function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/">
<Route
path="home"
element={
<ProtectedRoutes
isLoggedIn={JSON.parse(localStorage.getItem("isLoggedIn"))}
>
<Home />
</ProtectedRoutes>
}
/>
<Route path="login" element={<Login />} />
<Route path="signup" element={<Signup />} />
</Route>
</Routes>
</BrowserRouter>
);
}
Login
import React from "react";
import { useRef, useState } from "react";
import { Button, Card, Form, Alert, Container } from "react-bootstrap";
import { signInWithEmailAndPassword } from "firebase/auth";
import { auth } from "../firebaserc";
import { Link, useNavigate } from "react-router-dom";
export default function Login() {
const emailRef = useRef();
const passwordRef = useRef();
const [error, setError] = useState("");
const [loading, setLoading] = useState(false);
const navigate = useNavigate();
const handleSubmit = (e) => {
e.preventDefault();
signInWithEmailAndPassword(
auth,
emailRef.current.value,
passwordRef.current.value
)
.then((userCredential) => {
// Signed in
const user = userCredential.user;
// ...
console.log(user);
localStorage.setItem("isLoggedIn", true);
if (JSON.parse(localStorage.getItem("isLoggedIn"))) {
navigate("/home");
}
setError("");
})
.catch((error) => {
setError(error.message);
});
};
return (
<>
<Container
className="d-flex align-items-center justify-content-center"
style={{
minHeight: "100vh",
}}
>
<div
className="w-100"
style={{
maxWidth: "400px",
}}
>
<Card>
<Card.Body>
<h2 className="text-center mb-3">Login</h2>
{error && <Alert variant="danger">{error}</Alert>}
<Form onSubmit={handleSubmit}>
<Form.Group id="email" className="mb-2">
<Form.Label>Email</Form.Label>
<Form.Control type="email" ref={emailRef} required />
</Form.Group>
<Form.Group id="password" className="mb-2">
<Form.Label>Password</Form.Label>
<Form.Control type="password" ref={passwordRef} required />
</Form.Group>
<Button disabled={loading} className="w-100 mt-2" type="submit">
Login
</Button>
</Form>
</Card.Body>
</Card>
<div className="w-100 text-center mt-2">
New here? <Link to="/signup">Signup</Link>
</div>
</div>
</Container>
</>
);
}
Signup
import React from "react";
import { useRef, useState } from "react";
import { Button, Card, Form, Alert, Container } from "react-bootstrap";
import { createUserWithEmailAndPassword } from "firebase/auth";
import { auth } from "../firebaserc";
import { Link, useNavigate } from "react-router-dom";
export default function Signup() {
const emailRef = useRef();
const passwordRef = useRef();
const [error, setError] = useState("");
const [loading, setLoading] = useState(false);
const navigate = useNavigate();
const handleSubmit = (e) => {
e.preventDefault();
createUserWithEmailAndPassword(
auth,
emailRef.current.value,
passwordRef.current.value
)
.then((userCredential) => {
// Signed in
const user = userCredential.user;
console.log(user);
setError("");
navigate("/home");
localStorage.setItem("isLoggedIn", true);
// ...
})
.catch((error) => {
setError(error.message);
// ..
});
};
return (
<>
<Container
className="d-flex align-items-center justify-content-center"
style={{
minHeight: "100vh",
}}
>
<div
className="w-100"
style={{
maxWidth: "400px",
}}
>
<Card>
<Card.Body>
<h2 className="text-center mb-3"> Sign Up</h2>
{error && <Alert variant="danger">{error}</Alert>}
<Form onSubmit={handleSubmit}>
<Form.Group id="email" className="mb-2">
<Form.Label>Email</Form.Label>
<Form.Control type="email" ref={emailRef} required />
</Form.Group>
<Form.Group id="password" className="mb-2">
<Form.Label>Password</Form.Label>
<Form.Control type="password" ref={passwordRef} required />
</Form.Group>
<Button disabled={loading} className="w-100 mt-2" type="submit">
Sign Up
</Button>
</Form>
</Card.Body>
</Card>
<div className="w-100 text-center mt-2">
Already have an account <Link to="/login">Login</Link>
</div>
</div>
</Container>
</>
);
}
Home
import React from "react";
import { Button } from "react-bootstrap";
import { auth } from "../firebaserc";
import { signOut } from "firebase/auth";
import { useNavigate } from "react-router-dom";
export default function Home() {
const navigate = useNavigate();
const handleLogout = () => {
signOut(auth)
.then(() => {
// Sign-out successful.
localStorage.removeItem("isLoggedIn");
navigate("/login", { replace: true });
})
.catch((error) => {
// An error happened.
console.log(error.message);
});
};
return (
<div>
Home
<Button onClick={handleLogout}>Logout</Button>
</div>
);
}
Protected Routes
import { Navigate } from "react-router-dom";
const ProtectedRoutes = ({ isLoggedIn, children }) => {
if (!isLoggedIn) {
return <Navigate to="/login" replace />;
}
return children;
};
export default ProtectedRoutes;
Let's say you want to make a React App refresh ,
Simply
React.useEffect(() => {
doSomething();
}, [doSomething, IsAuthenticated ]);
once this values change it will update this component
This value need to be observable
firebase gives you that
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
// User is signed in.
} else {
// No user is signed in.
}
});
https://firebase.google.com/docs/auth/web/manage-users
and with react you can also make
firebase.auth().onAuthStateChanged((user) => {
if (user) {
handleLogin(user);
} else {
Logout();
}
});
function Logout() {
setAuthintecated(false)
};
Also here some resource for you
https://www.freecodecamp.org/news/react-firebase-authentication-and-crud-operations/
GoodLuck
I'm using Laravel on the backend and react.js on the frontend , when I try to login it will redirect to the home ("/") but when I refresh the page I am redirected to login page again. I am using rote protection file which takes component as a parameter and all the components passed in protected route are only accessible by logged in users.. after logging in when I try to access protected pages I am redirected to login page.. can any body help?
app.js
function App() {
return (
<div className="App">
{/* <AuthContextProvider> */}
<BrowserRouter>
<Switch>
<Route path = "/login"><Login/></Route>
<Route path= "/register"><Register/></Route>
<Route path = "/add"><AuthProtection component = {AddProduct}/> </Route>
<Route path = "/update"><AuthProtection component = {UpdateProduct}/> </Route>
<Route path = "/search"><AuthProtection component = {Search}/> </Route>
<Route path = "/"><AuthProtection component = {Home}/> </Route>
</Switch>
</BrowserRouter>
{/* </AuthContextProvider> */}
</div>
);
}
export default App;
login.js
export const Login = () => {
const history = useHistory()
const [email, setemail] = React.useState("")
const [password, setpass] = React.useState("")
const loginuser = e =>{
e.preventDefault();
axios.defaults.withCredentials = true;
let data = {email,password}
axios.get('http://localhost:8000/sanctum/csrf-cookie').then(response => {
console.log(response)
axios.post('http://localhost:8000/login',data ,{
headers: {
'Content-Type': 'application/json',
"Accept": "application/json",
'X-XSRF-TOKEN': (() => {
const name = 'XSRF-TOKEN'
const cookies = '; ' + document.cookie
const parts = cookies.split('; ' + name + '=')
const value = parts.length == 2 ? parts.pop().split(';').shift() : null
console.log('>>> XSRF-TOKEN', value)
return value
})(),
},
}).then(response => {
localStorage.setItem("user-info" , JSON.stringify(response.config.headers["X-XSRF-TOKEN"]))
Auth.authenticate();
history.push("/");
});
});
}
return (
<>
<Header/>
<div>
<div className="wrapper fadeInDown">
<div id="formContent">
{/* Tabs Titles */}
{/* Icon */}
<div className="fadeIn first">
</div>
{/* Login Form */}
<form onSubmit = {loginuser}>
<input type="text" value={email} onChange={(e)=>setemail(e.target.value)} className="fadeIn second" placeholder="login" />
<input type="password" value={password} onChange={(e)=>setpass(e.target.value)} className="fadeIn third" placeholder="password" />
<button type="submit" className="fadeIn fourth btn btn-primary" >LOGIN</button>
</form>
{/* Remind Passowrd */}
<div id="formFooter">
<a className="underlineHover" href="#">Forgot Password?</a>
</div>
</div>
</div>
</div>
</>
)
}
Auth.js
const Auth = {
isAuthenticated: false,
authenticate() {
this.isAuthenticated = true;
},
signout() {
this.isAuthenticated = false;
},
getAuth() {
return this.isAuthenticated;
}
};
export default Auth;
protectedRoutes.js
import React from 'react'
import { useHistory } from 'react-router'
import Auth from './Auth'
import { AuthContext } from './AuthContext';
export const AuthProtection = (props) => {
console.log(props)
const history = useHistory()
let ProtectedTemplate = props.component
console.log(Auth.getAuth())
React.useEffect(()=>{
if( !Auth.getAuth() ){
history.push("/login")
}
})
return (
<div>
<ProtectedTemplate/>
</div>
)
}
Here's my app component that renders an input for user to type in. What I want to achieve is that whatever input that the user writes in will be passed down to the Films component. That text is then will be used as a query param to get data from an api endpoint
import React, { useState } from "react";
import Films from "../Films";
import { BrowserRouter as Router, Route } from "react-router-dom";
import "./style.css";
const App = () => {
const [text, setText] = useState("");
const [redirect, setRedirect] = useState(false);
const onSubmit = (event) => {
setRedirect(true);
};
return (
<Router>
<div>
<p className="films-analysis-service">Films Analysis Service </p>
<form id="input-form" onSubmit={onSubmit}>
<input
type="text"
id="input-box"
value={text}
onChange={(e) => setText(e.target.value)}
/>
<button className="button" type="submit">
Search
</button>
</form>
{redirect && (
<Route
exact
path="/films"
render={(props) => <Films text={text} />}
/>
)}
</div>
</Router>
);
};
export default App;
This is my Films component:
import React, { useEffect, useState } from "react";
import "./style.css";
const axios = require("axios");
const Films = ({ text }) => {
const [movies, setMovies] = useState([]);
const fetchMoviesByDirectorName = () => {
let config = {
headers: { Authorization: apiKey },
params: {
directorName: text, //the text that is passed down from App component
},
};
axios.get(filmsEndpointURL, config);
};
useEffect(() => {
fetchMoviesByDirectorName();
}, [movies]);
return (
...
);
};
export default Films;
At the moment I'm just trying to print out the data that I would get back but unfortunately I don't think my input value is passed down properly. I don't think my usage of Route is correct.. and it's not redirecting to /films component. What changes should I do to my App.js?
Make sure to do event.preventDefault() in onSubmit
const onSubmit = (event) => {
event.preventDefault(); //<----- like this
setRedirect(true);
};
You can use Redirect to navigate to Films not Route.
Refactored code (using Redirect)
<Router>
<div>
<p className="films-analysis-service">Films Analysis Service </p>
<form id="input-form" onSubmit={onSubmit}>
<input
type="text"
id="input-box"
value={text}
onChange={(e) => setText(e.target.value)}
/>
<button className="button" type="submit">
Search
</button>
</form>
<Route exact path="/films" render={(props) => <Films text={text} {...props}/>} /> //<----see here
{redirect && <Redirect to="/films" />} //<----see here
</div>
<Route></Route>
</Router>;
You can also use history object to navigate to Films
import { createBrowserHistory } from "history";
const customHistory = createBrowserHistory();
const App = () => {
const [text, setText] = useState("");
const [redirect, setRedirect] = useState(false);
const onSubmit = (event) => {
// setRedirect(true);//<----no need
customHistory.push("/films");
};
return (
<Router history={customHistory}>
<div>
<p className="films-analysis-service">Films Analysis Service </p>
<form id="input-form" onSubmit={onSubmit}>
<input
type="text"
id="input-box"
value={text}
onChange={(e) => setText(e.target.value)}
/>
<button className="button" type="submit">
Search
</button>
</form>
<Route exact path="/films" render={(props) => <Films text={text} />} />
</div>
</Router>
);
};
export default App;