Im implementing a basic login which checks wether a user is in a list or not, if it is, then put the username into localStorage and then redirect to ("/") based on the console.log it sais that it got redirected but it doesnt actually redirect:
import { useNavigate } from 'react-router-dom';
function Login({ fakeData }) {
const [username, setUsername] = useState('');
const navigate = useNavigate();
const handleSubmit = async (event) => {
event.preventDefault();
console.log('Submitting login form');
console.log('Username: ' + username);
// Check if user with entered username exists
const userExists = fakeData.users.find((user) => user.username === username);
if (userExists) {
console.log('User exists. Redirecting to /');
localStorage.setItem('loggedInUser', username); // Set username in localStorage
navigate('/');
} else {
// Clear username
setUsername('');
console.log('User does not exist.');
// Handle invalid username case (display error message, etc.)
}
};
return (
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100vh' }}>
<div style={{ padding: '1rem', border: '1px solid black', borderRadius: '8px', width: '300px' }}>
<form onSubmit={handleSubmit}>
<div style={{ marginBottom: '1rem', display: 'flex', alignItems: 'center' }}>
<label htmlFor="username" style={{ marginRight: '0.5rem' }}>
Username:
</label>
<input
type="text"
id="username"
value={username}
onChange={(event) => setUsername(event.target.value)}
/>
</div>
<div style={{ display: 'flex', justifyContent: 'center' }}>
<button type="submit" className="btn btn-primary">
Login
</button>
</div>
</form>
</div>
</div>
);
}
export default Login;
as you see it gets printed out, but it still stays on /login
import React from 'react';
import {BrowserRouter as Router, Routes, Route, Navigate} from 'react-router-dom';
import Dashboard from "./components/Dashboard";
import DifficultyComparison from "./components/comparisons/DifficultyComparison";
import RestrictionComparison from "./components/comparisons/RestrictionComparison";
import EnvironmentComparison from "./components/comparisons/EnvironmentComparison";
import CurrentContributionComparison from "./components/comparisons/CurrentContributionComparison";
import AllowsMeToComparison from "./components/comparisons/AllowsMeToComparison";
import SustainableDevelopmentComparison from "./components/comparisons/SustainableDevelopmentComparison";
import 'bootstrap/dist/css/bootstrap.min.css';
import {useState} from "react";
import Login from "./components/Login";
const App = () => {
const [fakeData, setFakeData] = useState({
//Unnecessarly Long js object
});
const [selectedOption1, setSelectedOption1] = useState('Max Mustermann');
const [selectedOption2, setSelectedOption2] = useState('Challenge');
const [selectedOption3, setSelectedOption3] = useState([]);
const loggedInUser = localStorage.getItem('loggedInUser');
return (
<Router>
<Routes>
{!loggedInUser && <Route path="/*" element={<Navigate to="/login"/>}/>}
<Route path="/login" element={<Login fakeData={fakeData}/>}/>
<Route
path="/"
element={
loggedInUser ? (
<Dashboard
fakeData={fakeData}
selectedOption1={selectedOption1}
setSelectedOption1={setSelectedOption1}
selectedOption2={selectedOption2}
setSelectedOption2={setSelectedOption2}
selectedOption3={selectedOption3}
setSelectedOption3={setSelectedOption3}
/>
) : (
<Navigate to="/login"/>
)
}
/>
<Route
path="/difficulty"
element={
loggedInUser ? (
<DifficultyComparison
fakeData={fakeData}
selectedOption1={selectedOption1}
setSelectedOption1={setSelectedOption1}
selectedOption2={selectedOption2}
setSelectedOption2={setSelectedOption2}
selectedOption3={selectedOption3}
setSelectedOption3={setSelectedOption3}
/>
) : (
<Navigate to="/login"/>
)
}
/>
<Route
path="/restriction"
element={
loggedInUser ? (
<RestrictionComparison
fakeData={fakeData}
selectedOption1={selectedOption1}
setSelectedOption1={setSelectedOption1}
selectedOption2={selectedOption2}
setSelectedOption2={setSelectedOption2}
selectedOption3={selectedOption3}
setSelectedOption3={setSelectedOption3}
/>
) : (
<Navigate to="/login"/>
)
}
/>
<Route
path="/environment"
element={
loggedInUser ? (
<EnvironmentComparison
fakeData={fakeData}
selectedOption1={selectedOption1}
setSelectedOption1={setSelectedOption1}
selectedOption2={selectedOption2}
setSelectedOption2={setSelectedOption2}
selectedOption3={selectedOption3}
setSelectedOption3={setSelectedOption3}
/>
) : (
<Navigate to="/login"/>
)
}
/>
<Route
path="/currentcontribution"
element={
loggedInUser ? (
<CurrentContributionComparison
fakeData={fakeData}
selectedOption1={selectedOption1}
setSelectedOption1={setSelectedOption1}
selectedOption2={selectedOption2}
setSelectedOption2={setSelectedOption2}
selectedOption3={selectedOption3}
setSelectedOption3={setSelectedOption3}
/>
) : (
<Navigate to="/login"/>
)
}
/>
<Route
path="/allowsmeto"
element={
loggedInUser ? (
<AllowsMeToComparison
fakeData={fakeData}
selectedOption1={selectedOption1}
setSelectedOption1={setSelectedOption1}
selectedOption2={selectedOption2}
setSelectedOption2={setSelectedOption2}
selectedOption3={selectedOption3}
setSelectedOption3={setSelectedOption3}
/>
) : (
<Navigate to="/login"/>
)
}
/>
<Route
path="/sustainabledevelopment"
element={
loggedInUser ? (
<SustainableDevelopmentComparison
fakeData={fakeData}
selectedOption1={selectedOption1}
setSelectedOption1={setSelectedOption1}
selectedOption2={selectedOption2}
setSelectedOption2={setSelectedOption2}
selectedOption3={selectedOption3}
setSelectedOption3={setSelectedOption3}
/>
) : (
<Navigate to="/login"/>
)
}
/>
</Routes>
</Router>
);
};
export default App;
it should also be said that in the website i did use d3.js which also changes the virtual dom and im doing refreshes here and there to update charts and such, so what i think happened is that it redirects, but there kinda is a conflict with the dom or so and it reloads? idk ill provide
a code sample aswell:
import * as d3 from 'd3';
function CommitmentsBar({
data,
width,
height,
fakeData,
selectedOption1,
selectedOption2,
selectedOption3,
setSelectedOption1,
setSelectedOption2,
setSelectedOption3
}) {
let eingeloeste = [];
const cId = fakeData.commitments.filter(commitment => commitment.commitmentname === selectedOption2)[0].commitmentid;
if (cId >= 0) {
const cId = fakeData.commitments.filter(commitment => commitment.commitmentname === selectedOption2)[0].commitmentid;
selectedOption3.map(option => {
const groupOfUsers = fakeData.groups.filter(group => group.groupname === option)[0].users;
const diariesFromCiD = fakeData.diary.filter(diary => diary.commitmentid === cId);
const selectedDiaries = diariesFromCiD.filter(diary => groupOfUsers.includes(diary.userid));
const eingeloest = selectedDiaries.map(diary => diary.eingeloest);
const sum = eingeloest.reduce((a, b) => a + b, 0);
const avg = sum / groupOfUsers.length || 0;
eingeloeste.push(avg);
return avg;
});
}
data = eingeloeste.length > 0 ? eingeloeste : [];
const groups = selectedOption3
const colors = ["#85B3B7"];
const svgRef = useRef();
useEffect(() => {
const svg = d3.select(svgRef.current)
.attr("width", width)
.attr("height", height)
.style('overflow', 'visible');
const xScale = d3.scaleBand()
.domain(data.map((value, index) => index))
.range([0, width])
.padding(0.5);
const yScale = d3.scaleLinear()
.domain([0, 28])
.range([height, 0]);
const xAxis = d3.axisBottom(xScale)
.tickFormat((value, index) => groups[index])
.tickSize(0);
const yAxis = d3.axisLeft(yScale)
.ticks(6)
.tickValues([5, 10, 15, 20, 25, 28]);
svg.selectAll('g').remove();
svg.append('g')
.call(xAxis)
.attr('transform', `translate(0, ${height})`)
.selectAll('text')
.style('font-size', '16px');
svg.append('g')
.call(yAxis)
.selectAll('text')
.style('fill', 'black')
.style('font-size', '16px');
const horizontalLines = d3.axisLeft(yScale)
.ticks(5)
.tickSize(-width)
.tickFormat('')
.tickSizeOuter(0);
svg.append('g')
.call(horizontalLines)
.attr('class', 'horizontal-lines')
.selectAll('.tick line')
.attr('stroke', 'lightgrey')
.attr('stroke-width', 1)
.attr('stroke-dasharray', '4 4');
const group = svg.selectAll('.group')
.data(data)
.join('g')
.attr('class', 'group');
group.append('rect')
.attr('class', 'bar')
.attr('x', (value, index) => xScale(index))
.attr('y', yScale)
.attr('width', xScale.bandwidth())
.attr('height', value => height - yScale(value))
.attr('fill', '#85B3B7');
group.each(function (d, i) {
if (i % 4 === 3) {
// Append a line and text to every 4th group
const groupIndex = Math.floor(i / 4);
d3.select(this)
.append('line')
.attr('class', 'line')
.attr('x1', xScale(i) + xScale.bandwidth() / 2 + 15)
.attr('y1', yScale(28))
.attr('x2', xScale(i) + xScale.bandwidth() / 2 + 15)
.attr('y2', yScale(28) - 30)
.attr('stroke', 'grey')
.attr('stroke-width', 1);
d3.select(this)
.append('text')
.attr('class', 'group-label')
.attr('x', xScale(i) + xScale.bandwidth() / 2 + 15)
.attr('y', yScale(28) - 35)
.text(`Klasse ${groupIndex + 1}`)
.style('font-size', '12px')
.style('text-anchor', 'middle');
}
});
const legendWidth = 80 * colors.length;
const legend = svg.append('g')
.attr('transform', `translate(${(width - legendWidth) / 2}, ${height - 20})`);
legend.selectAll('.legend-item')
.data(colors)
.join('g')
.attr('class', 'legend-item')
.attr('transform', (value, index) => `translate(${index * 80}, 0)`)
.call(g => {
g.append('rect')
.attr('x', 0)
.attr('y', -height)
.attr('width', 15)
.attr('height', 15)
.attr('fill', value => value);
g.append('text')
.attr('x', 20)
.attr('y', -height + 13)
.text(`Eingelöste Commitments`)
});
}, [data, groups, height, width, selectedOption3]);
return <svg ref={svgRef}/>;
}
export default CommitmentsBar;
2
Answers
adding a reload after the navigate did the job
I’d recommend you not to make the
loggedInUser
validation in the Router of your application based on how you’re handling the session of the user (which is the localStorage).I’d just make the distinction inside a
useEffect
hook at the beginning of your Dashboard component like this:But, ideally, I’d just implement a context in the application to handle data of the sort.