我正在實現一個基本登錄,它檢查用戶是否在列表中,如果是,則將用戶名放入localStorage 中,然後根據console.log 重定向到(“/”),它說它得到了已重定向,但實際上並未重定向:
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;
如您所見,它被印出來,但它仍然保留在 /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;
還應該說,在網站中我確實使用了d3.js,它也更改了虛擬dom,並且我在這裡和那裡進行刷新以更新圖表等,所以我認為發生的是它重定向,但有點與dom 或其他衝突,然後重新載入?我不知道我無法提供 還有程式碼範例:
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;
導航完成後新增重新載入