当父组件注入具有不同值的道具时,子组件不会触发渲染

  • 本文关键字:组件 注入 reactjs
  • 更新时间 :
  • 英文 :


以下是我的组件:

应用程序组件:

import logo from './logo.svg';
import {Component} from 'react';
import './App.css';
import {MonsterCardList} from './components/monster-list/monster-card-list.component'
import {Search} from './components/search/search.component'
class App extends Component
{

constructor()
{
super();
this.state = {searchText:""}
}
render()
{
console.log("repainting App component");
return (
<div className="App">
<main>
<h1 className="app-title">Monster List</h1>
<Search callback={this._searchChanged}></Search>
<MonsterCardList filter={this.state.searchText}></MonsterCardList>
</main>
</div>
);
}
_searchChanged(newText)
{
console.log("Setting state. new text: "+newText);
this.setState({searchText:newText}, () => console.log(this.state));
}
}
export default App;

卡片列表组件:

export class MonsterCardList extends Component
{
constructor(props) 
{
super(props);
this.state = {data:[]};
}

componentDidMount()
{
console.log("Component mounted");
this._loadData();
}
_loadData(monsterCardCount)
{
fetch("https://jsonplaceholder.typicode.com/users", {
method: 'GET',
}).then( response =>{
if(response.ok)
{
console.log(response.status);
response.json().then(data => {
let convertedData = data.map( ( el, index) => {
return {url:`https://robohash.org/${index}.png?size=100x100`, name:el.name, email:el.email}
});
console.log(convertedData);
this.setState({data:convertedData});
});
}
else
console.log("Error: "+response.status+" -> "+response.statusText);
/*let data = response.json().value;

*/
}).catch(e => {
console.log("Error: "+e);
});

}
render() 
{
console.log("filter:" + this.props.filter);
return (
<div className="monster-card-list">
{this.state.data.map((element,index) => {
if(!this.props.filter || element.email.includes(this.props.filter))
return <MonsterCard cardData={element} key={index}></MonsterCard>;
})}
</div>
);

}
}

卡片组件:

import {Component} from "react"
import './monster-card.component.css'
export class MonsterCard extends Component
{
constructor(props) 
{
super(props);
}
render() 
{
return (
<div className="monster-card">
<img className="monster-card-img" src={this.props.cardData.url}></img>
<h3 className="monster-card-name">{this.props.cardData.name}</h3>
<h3 className="monster-card-email">{this.props.cardData.email}</h3>
</div> 
);
}
}

搜索组件:

import {Component} from "react"
export class Search extends Component
{
_searchChangedCallback = null;
constructor(props)
{
super();
this._searchChangedCallback = props.callback;
}   

render()
{

return (
<input type="search" onChange={e=>this._searchChangedCallback(e.target.value)} placeholder="Search monsters"></input>
);
}
}

问题是,我看到了输入中键入的文本如何正确地流到应用程序组件,并调用了回调,但当_searchChanged中的状态发生变化时,MonsterCardList似乎不会重新呈现。

我看到你在MonsterCardList组件filter:this.props.searchText中使用状态filter。但你在这个组件中只传递了一个道具filter(filter={this.state.searchText}(。所以道具searchText是未定义的。

我看到您不需要使用状态filter。用this.props.filter代替this.state.filter

_loadData在以下代码中首次安装组件时只会被调用一次

componentDidMount()
{
console.log("Component mounted");
this._loadData();
}

当您在constructor内部设置state时,意味着它也会设置this.state.filter一次。当searchText道具发生变化时,状态不会发生变化,因此不会重新渲染。

constructor(props) 
{
super(props);
this.state = {data:[], filter:this.props.searchText};
}

如果您需要在道具更改时重新发送,请使用componentDidUpdate生命周期挂钩

componentDidUpdate(prevProps) 
{
if (this.props.searchText !== prevProps.searchText) 
{
this._loadData();
}
}

好吧,最后我发现了发生了什么。这不是一个与react相关的问题,而是一个javascript问题,与此相关的问题没有绑定到_searchChanged函数内的App类。

我们在构造函数中这样绑定它:

this._searchChanged = this._searchChanged.bind(this); 

或者我们只使用箭头功能:

_searchChanged = (newText) => 
{
console.log("Setting state. new text: "+newText);
this.setState({filter:newText}, () => console.log(this.state));
}

一切如预期。

最新更新