gpt4 book ai didi

javascript - 组件仅在单击两次后更新 React

转载 作者:行者123 更新时间:2023-11-30 14:16:49 26 4
gpt4 key购买 nike

我正在构建一个 React 应用程序,除其他外,它会在单击按钮时生成一个随机数,然后将一组 JSON 对象过滤为仅位于该随机数索引处的对象(即 JSON[random]) .通常应用程序应该在过滤 JSON 对象数组后重新呈现,但由于某种原因,在第一次单击按钮并随机选择时,需要两次单击才能更新。从那时起,它会按预期更新,每次单击按钮时都会进行新的随机渲染。

我不确定问题是来自 App.js 还是更低的地方。在第一次点击时,它会生成一个新的随机数,并且应该将其保存到状态,但无法立即重新渲染。在随后的点击中,事情似乎会根据先前生成的随机数进行更新,同时将一个新的随机数放入队列中。我更希望这一切一次性发生:单击、生成随机数、保存到状态、更新以反射(reflect)新的随机 à la JSON[random]。

这可能与我实现生命周期方法的方式有关,因为我承认我不确定每个方法的所有细微差别,只是尝试使用任何一个似乎可以做我想做的事情。如果您有任何建议,请告诉我...

谢谢!

相关文件如下:

App.js - 在 Header.state.randomClicks 中注册新点击时生成并存储随机值

class App extends Component {
constructor(props){
super(props)
this.state = {headerLink: "", searchValue: "", random: 0, randomClicks: 0}

this.generateRandom = this.generateRandom.bind(this);
}

getLinkFromHeader = (link) => {
if (this.state.headerLink !== link) {
this.setState({
headerLink: link,
})
}
}

getSearchValueFromHeader = (string) => {
this.setState({
searchValue: string,
});
}

getRandomMax = (max) => {
this.setState({
randomMax: max,
})
}

getRandomClicks = (value) => {
this.setState({
randomClicks: value,
})
}

generateRandom(number) {
let random = Math.floor(Math.random() * number) + 1;
console.log("generateRandom = ", random)
return random
}

shouldComponentUpdate(nextProps, nextState) {
return this.state.randomClicks !== nextState.randomClicks;
}

componentWillUpdate() {}

componentDidUpdate(prevState) {
let randomClicks = this.state.randomClicks;
console.log("this.state.randomClicks: ", this.state.randomClicks)
// console.log("prevState: ", prevState)
// console.log("prevState.randomClicks = ", prevState.randomClicks)
// ^^ is this a bug ? ^^
let random = this.generateRandom(this.state.randomMax);
if (this.state.random !== random) {
this.setState({random: random})
}
}

render() {
return (
<div className="App background">
<div className="content">
<Header getLinkFromHeader={this.getLinkFromHeader} getSearchValueFromHeader={this.getSearchValueFromHeader} randomClick={this.randomClick} getRandomClicks={this.getRandomClicks}/>
<TilesContainer link={this.state.headerLink} searchValue={this.state.searchValue} getRandomMax={this.getRandomMax} random={this.state.random} randomClicks={this.state.randomClicks}/>
</div>
</div>
);
}
}

export default App

Header.js* - 每次点击 RandomButton 时,randomClick 计数都会增加

class Header extends Component {
constructor(props){
super(props);
this.state = { selectorLink: "", searchValue: "", randomClicks: 0 }

this.randomClick = this.randomClick.bind(this);
}


getLinkFromSelector = (link) => {
this.setState({
selectorLink: link,
})
}

getSearchValue = (string) => {
this.setState({
searchValue: string,
})
}

shouldComponentUpdate(nextProps, nextState) {
console.log("this.state !== nextState: ", this.state !== nextState)
return this.state !== nextState;
}

componentDidUpdate(previousState){
if(this.state.selectorLink !== previousState.selectorLink) {
this.props.getLinkFromHeader(this.state.selectorLink);
}
this.props.getSearchValueFromHeader(this.state.searchValue);
this.props.getRandomClicks(this.state.randomClicks);
console.log("Header Did Update")
}

randomClick(){
this.props.randomClick;
this.setState({
randomClicks: this.state.randomClicks += 1,
});
}

render(){
return(
<div id="header" className="header">

<div className="title-div">
<div className="h1-wrapper title-wrapper">
<h1>Pokédex Viewer App</h1>
</div>
</div>

<PokedexSelector getLinkFromSelector={this.getLinkFromSelector}/>

<SearchBar getSearchValue={this.getSearchValue}/>

<button type="button" id="random-button" onClick={this.randomClick}>Random Pokémon</button>
<button type="button" id="show-all-button" onClick={this.showAllClick}>Show All</button>

</div>
)
}
}

export default Header

TilesContainer.js - 发送来自 App 的随机数并过滤/重新呈现图 block 列表

class TilesContainer extends Component {

constructor(props){
super(props);
this.state = {
pokemon: [],
filteredPokemon: [],
randomMax: 0,
showDetails: false,
};
this.getPokemon = this.getPokemon.bind(this);
this.tiles = this.tiles.bind(this);
this.getPokemon(this.props.link);
}

getPokemon(pokedexLink) {
let link = "";
(pokedexLink === "")
? link = "https://pokeapi.co/api/v2/pokedex/national/"
: link = this.props.link;
fetch(link)
.then(response => response.json())
.then(myJson => {
let list = myJson['pokemon_entries'];
this.setState({
pokemon: list,
randomMax: list.length,
})
this.props.getRandomMax; // send randomMax to App
})
}

filterPokemon(string) {
if (string !== "") {
console.log("string: ", string)
string = string.toString().toLowerCase()
let filteredPokemon = this.state.pokemon.filter(pokemon => {
const name = pokemon.pokemon_species.name;
const nameStr = name.slice(0,string.length);
const number = pokemon.entry_number;
const numberStr = number.toString().slice(0, string.length);
return (this.state.random !== 0) ? number.toString() === string : nameStr === string || numberStr === string;
})
if (this.props.randomClicks !== 0) { // i.e. using a random
this.setState({
filteredPokemon: filteredPokemon,
})
} else {
this.setState({
filteredPokemon: filteredPokemon,
randomMax: filteredPokemon.length,
})
}
} else {
this.setState({
filteredPokemon: [],
randomMax: this.state.pokemon.length,
})
}
}


componentDidUpdate(prevProps, prevState) {
if (this.props.link !== prevProps.link) {
this.getPokemon(this.props.link)
}
if (this.props.searchValue !== prevProps.searchValue) {
this.filterPokemon(this.props.searchValue)
}
if (this.state.randomMax !== prevState.randomMax){
this.props.getRandomMax(this.state.randomMax);
}
if (this.props.random !== prevProps.random) {
console.log("TilesContainer random: ", this.props.random)
this.filterPokemon(this.props.random)
}
}

tiles() {
console.log("tiles() filteredPokemon: ", this.state.filteredPokemon)
console.log("tiles() searchValue: ", this.props.searchValue)
console.log("tiles() random: ", this.props.random)
if (this.state.pokemon.length > 0) {
if (this.state.filteredPokemon.length == 0 && this.props.searchValue === ""){
return (
this.state.pokemon.map(pokemon => (
<Tile key={pokemon.entry_number} number={pokemon.entry_number} name={pokemon.pokemon_species.name} url={pokemon.pokemon_species.url}/>
))
)
} else if (this.state.filteredPokemon.length > 0){
return (
this.state.filteredPokemon.map(pokemon => (
<Tile key={pokemon.entry_number} number={pokemon.entry_number} name={pokemon.pokemon_species.name} url={pokemon.pokemon_species.url}/>
))
)
}

}
}

render(){
return (
<div id="tiles-container"
className="tiles-container">
{this.tiles()}
</div>
)
}
}

export default TilesContainer

最佳答案

您不应该在 setState 中使用当前状态,也不应该直接修改状态。你实际上并没有调用 this.props.randomClick 并且它是未定义的。变化

randomClick(){
this.props.randomClick;
this.setState({
randomClicks: this.state.randomClicks += 1,
});
}

randomClick(){
if (typeof(this.props.randomClick) === 'function') this.props.randomClick();
this.setState(olState => ({
randomClicks: olState.randomClicks + 1,
}));
}

同时检查您的 shouldComponentUpdate 方法。它们可能有问题或多余。看起来您在 state.random 更改时阻止更新 App。因此,每次单击按钮时,都会存储新的随机值,但会使用前一个。因此,对于初始渲染和第一次点击,您使用 random: 0

我想 getRandomClicks 应该是 setRandomClicks

关于javascript - 组件仅在单击两次后更新 React,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53456678/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com