Reactjs 当父组件使用不同的值注入道具时,子组件不触发渲染
以下是我的组件: 应用程序组件:Reactjs 当父组件使用不同的值注入道具时,子组件不触发渲染,reactjs,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' c
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>
);
}
}
从“/logo.svg”导入徽标;
从“react”导入{Component};
导入“/App.css”;
从“./components/monster list/monster card list.component”导入{monster cardlist}
从“./components/Search/Search.component”导入{Search}
类应用程序扩展组件
{
构造函数()
{
超级();
this.state={searchText:}
}
render()
{
log(“重新绘制应用程序组件”);
返回(
怪物名单
);
}
_searchChanged(新文本)
{
console.log(“设置状态.新文本:“+newText”);
this.setState({searchText:newText},()=>console.log(this.state));
}
}
导出默认应用程序;
卡片列表组件:
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>
);
}
}
导出类MonsterCardList扩展组件
{
建造师(道具)
{
超级(道具);
this.state={data:[]};
}
componentDidMount()
{
控制台日志(“组件安装”);
这是。_loadData();
}
_loadData(monsterCardCount)
{
取回(“https://jsonplaceholder.typicode.com/users", {
方法:“GET”,
})。然后(响应=>{
if(response.ok)
{
console.log(响应状态);
response.json().then(数据=>{
让convertedData=data.map((el,index)=>{
返回{url:`https://robohash.org/${index}.png?size=100x100`,名称:el.name,电子邮件:el.email}
});
console.log(convertedData);
this.setState({data:convertedData});
});
}
其他的
console.log(“错误:“+response.status+”->“+response.statusText”);
/*让data=response.json().value;
*/
}).catch(e=>{
控制台日志(“错误:+e”);
});
}
render()
{
log(“filter:+this.props.filter”);
返回(
{this.state.data.map((元素,索引)=>{
如果(!this.props.filter | | element.email.includes(this.props.filter))
返回;
})}
);
}
}
卡组件:
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>
);
}
}
从“react”导入{Component}
导入“./monster card.component.css”
导出类扩展组件
{
建造师(道具)
{
超级(道具);
}
render()
{
返回(
{this.props.cardData.name}
{this.props.cardData.email}
);
}
}
搜索组件:
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>
);
}
}
从“react”导入{Component}
导出类搜索扩展组件
{
_searchChangedCallback=null;
建造师(道具)
{
超级();
这.\u searchChangedCallback=props.callback;
}
render()
{
返回(
这是.\u searchChangedCallback(e.target.value)}占位符=“搜索怪物”>
);
}
}
问题是,我看到输入中键入的文本如何正确地流向应用程序组件并调用回调,但是,当在“searchChanged”中更改状态时,MonsterCardList似乎不会重新呈现。
\u loadData
在下面的代码中首次装入组件时,只会调用一次
componentDidMount()
{
console.log("Component mounted");
this._loadData();
}
当您在构造函数中设置状态时
意味着它也会设置此.state.filter
一次。当searchText
道具更改时,状态不会更改,因此不会重新播放
constructor(props)
{
super(props);
this.state = {data:[], filter:this.props.searchText};
}
如果您需要在道具更改时重新播放,请使用componentdiddupdate
lifecyclehook
componentDidUpdate(prevProps)
{
if (this.props.searchText !== prevProps.searchText)
{
this._loadData();
}
}
我看到您在
MonsterCardList
组件中使用了statefilter
:filter:this.props.searchText
。但是您只在该组件中传递了一个propfilter
(filter={this.state.searchText}
)。因此,propssearchText
未定义
我看到您不需要使用state
过滤器
。用this.props.filter替换this.state.filter
,<。这不是一个与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));
}
一切正常。@不错,看看这个!!这不是我想要的。我不想每次组件更新时都触发loadData。我们的想法是这样做一次(这只是一个测试,从api检索的代码稍后不会出现在这个组件中)。因此,正如下面的用户所说,我已经更改了对渲染方法中道具的访问权限(谢谢!)。据我所知,当应用程序组件从搜索组件获取数据并执行设置状态时,这将触发moster卡列表渲染,该渲染将使用注入的新道具。但这不起作用。为什么?啊,是的,谢谢你。我经常玩代码,把那部分放在这里了。我已经编辑了这个问题来访问怪物卡列表中的道具,而不是状态。现在不是应该更新吗?因为从应用组件,状态被改变,并且注入了一个新的过滤器道具。但是仍然没有触发渲染方法。没有取消它。你不需要这样捆绑。可以使用箭头函数表示法自动将函数绑定到此上下文。