使用react hook处理过滤器下拉菜单时保留URL和状态



我是react和hooks的新手,我试图实现一个过滤器,其中最后选择的过滤器选项将设置下拉开关上的值,但同时在选择过滤器时更改URL。

我的问题是我只能做其中一个,而不能两者兼得。这是我的过滤器下拉组件:

import React, { useState } from 'react'
import { Dropdown } from  'react-bootstrap';

function FilterDropDown ({onFilterChange}) {
const handleSelect=(e)=>{
console.log(e);
}
const onDropDownChange = (dropDownValue) => setGenreDropDown(dropDownValue);
const [genreDropDown, setGenreDropDown] = useState('')

return (
<Dropdown className="text-center m-3 p-auto">
<Dropdown.Toggle variant="success" id="dropdown-basic">
{genreDropDown}
</Dropdown.Toggle>
<Dropdown.Menu>
<Dropdown.Item href="#/Genre/Action" onClick={() => { onFilterChange("Action"); onDropDownChange("Action");}}>Action</Dropdown.Item>
<Dropdown.Item href="#/Genre/Adventure" onClick={() => { onFilterChange("Adventure"); onDropDownChange("Adventure");}}>Adventure</Dropdown.Item>
<Dropdown.Item href="#/Genre/Role-Playing" onClick={() => { onFilterChange("Role-Playing"); onDropDownChange("Role-Playing");}}>Role-Playing</Dropdown.Item>
</Dropdown.Menu>
</Dropdown>
)
}
export default FilterDropDown

这是我的App:

import React, { useState } from 'react';
import Navi from './Navi'
import CardGroup from './CardGroup'
import SearchBox from './SearchBox'
import './App.css';
import games from './csvjson.json';
import Content from './Content';
import FilterDropDown from './FilterDropDown'
// import Search from './search';
import {
HashRouter as Router,
Route,
useLocation
} from "react-router-dom";

function App()  {
const [searchfield, setSearchfield] = useState('')
const [filterField, setFilterField] = useState('')

const onSearchChange = (event) => {
setSearchfield(event.target.value)
// event.preventDefault();
}

const onFilterChange = (filterGenre) => setFilterField(filterGenre);

const filteredGames = games.filter(game => {
return (game.Title.toLowerCase().includes(searchfield.toLowerCase()) && game.genre.toLowerCase().includes(filterField.toLowerCase()))
})
return (
<Router>
<Route path="/" exact render={props => 
<div>
<Navi />
<SearchBox searchChange={onSearchChange}/>
<FilterDropDown onFilterChange={onFilterChange} />
<CardGroup games={filteredGames}/>
</div> }/>
<Route path="/games/:games" component={Content} />
{console.log("/"+`${filterField}`)}
<Route path={"/Genre/"+`${filterField}`} render={props => 
<div>
<Navi />
<SearchBox searchChange={onSearchChange}/>
<FilterDropDown onFilterChange={onFilterChange}/>
<CardGroup games={filteredGames}/>
</div> }
/>
</Router>
);
}

export default App;

您需要在父组件中拥有genereDropDown状态,并将其状态改变函数onDropDownChange传递给子组件FilterDropDown,如下所示。

import React, { useState } from "react";
import Navi from "./Navi";
import CardGroup from "./CardGroup";
import SearchBox from "./SearchBox";
import "./App.css";
import games from "./csvjson.json";
import Content from "./Content";
import FilterDropDown from "./FilterDropDown";
// import Search from './search';
import { HashRouter as Router, Route, useLocation } from "react-router-dom";
function App() {
const [searchfield, setSearchfield] = useState("");
const [filterField, setFilterField] = useState("");
const [genreDropDown, setGenreDropDown] = useState("");
const onDropDownChange = (dropDownValue) => setGenreDropDown(dropDownValue);
const onSearchChange = (event) => {
setSearchfield(event.target.value);
// event.preventDefault();
};
const onFilterChange = (filterGenre) => setFilterField(filterGenre);
const filteredGames = games.filter((game) => {
return (
game.Title.toLowerCase().includes(searchfield.toLowerCase()) &&
game.genre.toLowerCase().includes(filterField.toLowerCase())
);
});
return (
<Router>
<Route
path="/"
exact
render={(props) => (
<div>
<Navi />
<SearchBox searchChange={onSearchChange} />
<FilterDropDown onFilterChange={onFilterChange} />
<CardGroup games={filteredGames} />
</div>
)}
/>
<Route path="/games/:games" component={Content} />
{console.log("/" + `${filterField}`)}
<Route
path={"/Genre/" + `${filterField}`}
render={(props) => (
<div>
<Navi />
<SearchBox searchChange={onSearchChange} />
<FilterDropDown
onFilterChange={onFilterChange}
genreDropDown={genreDropDown}
onDropDownChange={onDropDownChange}
/>
<CardGroup games={filteredGames} />
</div>
)}
/>
</Router>
);
}
export default App;

然后在子组件中使用它们,如下所示。

import React from "react";
import { Dropdown } from "react-bootstrap";
function FilterDropDown({ onFilterChange, genreDropDown, onDropDownChange }) {
const handleSelect = (e) => {
console.log(e);
};
return (
<Dropdown className="text-center m-3 p-auto">
<Dropdown.Toggle variant="success" id="dropdown-basic">
{genreDropDown}
</Dropdown.Toggle>
<Dropdown.Menu>
<Dropdown.Item
href="#/Genre/Action"
onClick={() => {
onFilterChange("Action");
onDropDownChange("Action");
}}
>
Action
</Dropdown.Item>
<Dropdown.Item
href="#/Genre/Adventure"
onClick={() => {
onFilterChange("Adventure");
onDropDownChange("Adventure");
}}
>
Adventure
</Dropdown.Item>
<Dropdown.Item
href="#/Genre/Role-Playing"
onClick={() => {
onFilterChange("Role-Playing");
onDropDownChange("Role-Playing");
}}
>
Role-Playing
</Dropdown.Item>
</Dropdown.Menu>
</Dropdown>
);
}
export default FilterDropDown;

希望这能解决你的问题。