我想傳入filteredData子組件PokemonSearchBar.jsx以便我可以在父組件PokemonList.jsx中使用它來僅映射過濾后的 Pokemon。換句話說,當我進行搜索時,搜索組件會將e.target.value輸入中的字符與data陣列中的字符(填充所有口袋妖怪名稱)進行比較,該陣列作為道具從父組件PokemonList.jsx 傳遞. e.target.value如果和data陣列之間有一些共同的字符,則將只從輸入filteredData中接收具有共同字符的口袋妖怪。e.target.value
有什么方法可以將filteredData狀態作為 prop 傳遞給父組件?
這是子組件PokemonSearchBar.jsx:
import React, { useState } from 'react';
import { Link } from 'react-router-dom';
import './PokemonSearchBar.css';
import SearchIcon from '@mui/icons-material/Search';
import CloseIcon from '@mui/icons-material/Close';
export default function PokemonSearchBar({ placeholder, data }) {
const [filteredData, setFilteredData] = useState([]);
const [wordEntered, setWordEntered] = useState("");
const handleFilter = (e) => {
const searchWord = e.target.value;
setWordEntered(searchWord);
const newFilter = data.filter(value => {
return (value.name.toLowerCase().includes(searchWord.toLowerCase()));
});
if(searchWord === "") {
setFilteredData([]);
} else {
setFilteredData(newFilter);
}
}
const clearInput = (e) => {
setWordEntered("");
setFilteredData([]);
}
return (
<div className='search'>
<div className="row" style={{ display: 'flex', justifyContent: 'center' }}>
<div className="col-3"></div>
<div className="col-6">
<div className="searchInputs" style={{ display: 'flex', justifyContent: 'center'}}>
<input type="text" className="form-control rounded" placeholder={placeholder} onChange={handleFilter} value={wordEntered} />
{filteredData.length === 0 ? <button type="button" className="btn btn-primary"><SearchIcon /></button> : <button type="button" className="btn btn-warning"><CloseIcon onClick={clearInput} /></button>}
</div>
</div>
<div className="col-3"></div>
</div>
{filteredData.length !== 0 &&
<div className="dataResult mx-auto" style={{ display: 'flex', justifyContent: 'center' }}>
<ul>
{filteredData.slice(0, 15).map((pokemon) => {
return (<li style={{ listStyleType: 'none', textDecoration: 'none'}} className="dataItem"><Link to="/" className="a" style={{ textDecoration: 'none', color: 'black' }}>{pokemon.name}</Link></li>)
})}
</ul>
</div>
}
</div>
)
}
這是父組件PokemonList.jsx:
import React, { Component } from 'react'
import axios from 'axios'
import ReactPaginate from 'react-paginate';
import PokemonCard from './PokemonCard';
import PokemonSearchBar from './PokemonSearchBar';
export default class PokemonList extends Component {
state = {
url: "https://pokeapi.co/api/v2/pokemon?limit=100000&offset=0",
pokemon: [], // on créé un objet (qui va devenir un tableau) pokemon null c'est où on va enregistrer le json
pageNumber: 0,
pokemonsPerPage: 16
};
async componentDidMount() {
const res = await axios.get(this.state.url); // on attend de récupérer les pokemon avant d'exectuer la suite de la fonction
console.log(res.data['results']);
this.setState({pokemon: res.data['results']}); // on passe un objet dans le state et on affecte à pokemon le tableau résultats de la data de l'url
// setState re-render seulement les éléments qu'il faut re-rendre
};
render() {
console.log(this.state.pokemon);
const pagesVisited = this.state.pageNumber * this.state.pokemonsPerPage;
const displayUsers = this.state.pokemon
.slice(pagesVisited, pagesVisited this.state.pokemonsPerPage)
.map((pokemon) => {
return (
<PokemonCard
key={pokemon.name} // on utilise le props name comme clé unique car chaque nom de pokemon est unique
name={pokemon.name} // c'est le props name dans le pokemonCard
url={pokemon.url} // c'est le props url dans le pokemonCard
/> // on génère autant de cartes qu'il y a de pokemons dans le tableau results
)
});
const pageCount = Math.ceil(this.state.pokemon.length / this.state.pokemonsPerPage); // ceil() permet d'arrondir au supérieur
const changePage = ({selected}) => {
this.setState({pageNumber: selected})
}
return (
<React.Fragment>
<PokemonSearchBar data={this.state.pokemon} placeholder="Enter a Pokemon name" />
<br />
{this.state.pokemon ? ( // s'il y a quelquechose dans le state
<div className='row'>
{displayUsers}
<div style={{ display: 'flex', justifyContent: 'center'}}>
<ReactPaginate
previousLabel={"previous"}
nextLabel={"Next"}
pageCount={pageCount}
onPageChange={changePage}
containerClassName={"paginationButtons"}
previousLinkClassName={"previousButton"}
nextLinkClassName={"nextButton"}
disabledClassName={"paginationDisabled"}
activeClassName={"paginationActive"}
/>
</div>
</div>
) : (<h2>Loading Pokemon</h2>)}
{/* S'il n'y a rien dans le state afficher que le pokemon est en train de charger */}
</React.Fragment>
)
}
}
uj5u.com熱心網友回復:
在 React 中,基本上有 3 種方式來發送資料:
- 通過作為道具傳遞的回呼;
- 通過 Store(Redux 或 Context API 或其他)
- 通過本機自定義 Javascript 事件
您的用例可以通過 prop 實作:
import React, { useState } from 'react';
import { Link } from 'react-router-dom';
import './PokemonSearchBar.css';
import SearchIcon from '@mui/icons-material/Search';
import CloseIcon from '@mui/icons-material/Close';
export default function PokemonSearchBar({ placeholder, data, onDataFiltered }) {
const [filteredData, setFilteredData] = useState([]);
const [wordEntered, setWordEntered] = useState("");
const handleFilter = (e) => {
const searchWord = e.target.value;
setWordEntered(searchWord);
const newFilter = data.filter(value => {
return (value.name.toLowerCase().includes(searchWord.toLowerCase()));
});
if(searchWord === "") {
setFilteredData([]);
onDataFiltered([])
} else {
setFilteredData(newFilter);
onDataFiltered(newFilter)
}
}
const clearInput = (e) => {
setWordEntered("");
setFilteredData([]);
}
return (
<div className='search'>
<div className="row" style={{ display: 'flex', justifyContent: 'center' }}>
<div className="col-3"></div>
<div className="col-6">
<div className="searchInputs" style={{ display: 'flex', justifyContent: 'center'}}>
<input type="text" className="form-control rounded" placeholder={placeholder} onChange={handleFilter} value={wordEntered} />
{filteredData.length === 0 ? <button type="button" className="btn btn-primary"><SearchIcon /></button> : <button type="button" className="btn btn-warning"><CloseIcon onClick={clearInput} /></button>}
</div>
</div>
<div className="col-3"></div>
</div>
{filteredData.length !== 0 &&
<div className="dataResult mx-auto" style={{ display: 'flex', justifyContent: 'center' }}>
<ul>
{filteredData.slice(0, 15).map((pokemon) => {
return (<li style={{ listStyleType: 'none', textDecoration: 'none'}} className="dataItem"><Link to="/" className="a" style={{ textDecoration: 'none', color: 'black' }}>{pokemon.name}</Link></li>)
})}
</ul>
</div>
}
</div>
)
}
然后,您將像這樣宣告它:
<PokemonSearchBar
data={this.state.pokemon}
placeholder="Enter a Pokemon name"
onDataFiltered={(newData) => {
console.log("do something with the new data", newData);
}}
/>
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/504177.html
標籤:javascript 反应
