[英]React : how to pass a state from child to parent component
我想在子组件PokemonSearchBar.jsx中传递filteredData
数据,以便我可以在父组件PokemonList.jsx中使用它到 map 只过滤口袋妖怪。 换句话说,当我进行搜索时,搜索组件会将我输入的e.target.value
中的字符与data
数组(填充所有口袋妖怪名称)中的字符进行比较,该数组作为道具传递父组件PokemonList.jsx 。 如果e.target.value
和data
数组之间有一些共同的字符, filteredData
将只从输入中接收与e.target.value
的共同字符的口袋妖怪。
有什么方法可以将filteredData
state 作为道具传递给父组件?
这是子组件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>
)
}
}
在 React 中,基本上有 3 种方式来发送数据:
您的用例可以通过 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);
}}
/>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.