我有一个前端控制台,我试图做出反应,使用侧边菜单来过滤数据库中显示在动态生成的表格中的结果。
组件的层次结构如下:
App.js
|
|--SideMenu.js
|--ResultsTable.js
所以我理解父母可以访问子组件中的道具,也可以将道具传递给子组件。我试图做的是让sidemenu通过父App.js与结果表对话(除非有让孩子们直接沟通的方法吗?)并相应地更新表格,但是我和#39;我遇到了一个奇怪的问题。当我单击过滤器或重置按钮(在SideMenu.js中)时,在结果表组件中拾取道具的延迟需要我在注册之前单击按钮2或3次。我确信这个解决方案很简单,但到目前为止它还没有找到我。我认为当App.js将新道具传递回ResultTable.js时会出现问题,但我并不完全确定如何修复它。
这是我的SideMenu.js代码
export default class SideMenu extends React.Component{
constructor(){
super();
this.state={
serviceParam: '',
filterParam: '',
services: [],
}
this.handleServiceChoice = this.handleServiceChoice.bind(this);
this.handleSearch = this.handleSearch.bind(this);
this.getServices = this.getServices.bind(this);
this.handleReset = this.handleReset.bind(this);
}
componentWillMount(){
this.getServices();
}
getServices(){
const _this =this;
let servicesData;
let url = "http://mydevsite.ie/cgi-bin/log-queries/api/services";
fetch(url)
.then((resp) => resp.json())
.then(function(data){
servicesData = data;
console.log("servicesData");
console.log(servicesData);
_this.setState({
services: servicesData
});
});
}
handleReset(){
this.setState({
serviceParam: null,
filterParam: null,
});
let dropdownArrow = document.createElement("i");
dropdownArrow.setAttribute("class", "material-icons right");
dropdownArrow.innerHTML = "keyboard_arrow_down";
document.getElementById("serviceDisplay").innerHTML = "Services";
document.getElementById("serviceDisplay").appendChild(dropdownArrow);
this.props.filterCallback(this.state.serviceParam);
}
handleSearch(){
if(document.getElementById('search').value && this.state.serviceParam){
let filterParam = "&search="+document.getElementById('search').value;
console.log('In child - search 1');
console.log(filterParam);
let parentProps;
parentProps= this.state.serviceParam+filterParam;
this.props.filterCallback(parentProps);
} else if (document.getElementById('search').value){
let filterParam = "?search="+document.getElementById('search').value;
console.log('In child - search 2');
console.log(filterParam);
let parentProps;
parentProps=filterParam;
this.props.filterCallback(parentProps);
} else{
let filterParam = this.state.serviceParam;
console.log('In child - search 3');
console.log(filterParam);
let parentProps;
parentProps=filterParam;
this.props.filterCallback(parentProps);
}
}
handleServiceChoice(e){
console.log('sidebar target id');
console.log(e.target.id);
let serviceParam;
let dropdownArrow = document.createElement("i");
dropdownArrow.setAttribute("class", "material-icons right");
dropdownArrow.innerHTML = "keyboard_arrow_down";
document.getElementById("serviceDisplay").innerHTML = e.target.id;
document.getElementById("serviceDisplay").appendChild(dropdownArrow);
serviceParam = '?service='+e.target.id ;
this.setState({
serviceParam: serviceParam,
});
}
render(){
return(
<ul className="side-nav fixed blue accent-1">
<li className="logo"></li>
<li>
<a id="serviceDisplay" href="#" className="dropdown-button waves-effect" data-activates="services">Services<i className="material-icons right">keyboard_arrow_down</i></a>
<ul id="services" className="dropdown-content">
{this.state.services.map((dropdown)=>{
return(
<li key={dropdown.service}>
<a id={dropdown.service} href="#" className="waves-effect" onClick={this.handleServiceChoice}>{dropdown.service}</a>
</li>
);
})}
</ul>
</li>
<li className="bold"><a href="#">Supplier ID Search</a></li>
<li className="search">
<div className="container center-align">
<input id="search" type="text" placeholder="Enter ID here" className="validate blue accent-2"></input>
<button className="btn blue accent-2 waves-effect" type="submit" onClick={this.handleSearch}>
Filter
<i className="material-icons right">search</i>
</button>
</div>
</li>
<li >
<div className="container center-align">
<button className="btn blue accent-2 waves-effect" type="submit" onClick={this.handleReset}>
Reset Logs
<i className="material-icons right">autorenew</i>
</button>
</div>
</li>
</ul>
);
};
}
和ResultsTable.js:
export default class ResultsTable extends React.Component{
constructor(){
super();
this.state = {
logs: [],
xml: '',
render_xml: false,
}
this.ResultsTable = this.ResultsTable.bind(this);
this.handleRequestXML = this.handleRequestXML.bind(this);
this.handleResponseXML = this.handleResponseXML.bind(this);
this.returnToLogs = this.returnToLogs.bind(this);
this.renderTable = this.renderTable.bind(this);
this.renderXml = this.renderXml.bind(this);
}
componentWillMount(){
console.log('Child - In componentWillMount!');
this.ResultsTable();
}
componentWillReceiveProps(){
console.log('Child - In componentWillReceiveProps!');
console.log(this.props.filter);
this.ResultsTable();
}
returnToLogs(){
this.setState({
render_xml:false
});
}
handleResponseXML(e){
const _this =this;
_this.setState({
render_xml: true,
});
let id_param = '?_id='+e.target.id+'&type=response';
let url = "http://mydevsite.ie/cgi-bin/log-queries/api/xml"+id_param;
fetch(url)
.then((resp) => resp.json())
.then(function(data){
let xml = data;
console.log("xml");
console.log(xml);
_this.setState({
xml: xml,
});
});
}
handleRequestXML(e){
const _this =this;
_this.setState({
render_xml: true,
});
let id_param = '?_id='+e.target.id+'&type=request';
let url = "http://mydevsite.ie/cgi-bin/log-queries/api/xml"+id_param;
fetch(url)
.then((resp) => resp.json())
.then(function(data){
let xml = data;
console.log("xml");
console.log(xml);
_this.setState({
xml: xml,
});
});
}
ResultsTable(){
console.log('Child - In ResultsTable!');
console.log(this.props.filter);
const _this =this;
let logData;
let url = "http://mydevsite.ie/cgi-bin/log-queries/api/logs";
if(this.props.filter){
console.log('Child - Service Choice!');
console.log(this.props.filter);
url +=this.props.filter;
}
fetch(url)
.then((resp) => resp.json())
.then(function(data){
logData = data;
console.log("logData");
console.log(logData);
_this.setState({
logs: logData
});
});
}
renderTable(){
console.log('In renderTable!');
return (
<table className="highlight">
<thead>
<tr>
<th>ID</th>
<th>Created</th>
<th>Last Changed</th>
<th>Service</th>
<th>Supplier Identifier</th>
<th>Request XML</th>
<th>Response XML</th>
</tr>
</thead>
<tbody>
{this.state.logs.map((log)=>{
return(
<tr key={log._id}>
<td>{log._id}</td>
<td>{log.created}</td>
<td>{log.last_changed}</td>
<td>{log.service}</td>
<td>{log.supplier_identifier}</td>
<td><a id={log._id} onClick={this.handleRequestXML} href='#'>Click for XML</a></td>
<td><a id={log._id} onClick={this.handleResponseXML} href='#'>Click for XML</a></td>
</tr>
);
})}
</tbody>
</table>
);
}
renderXml(){
console.log("In renderXml");
return(
<div className="card-panel">
{this.state.xml}
<hr/>
<a className="waves-effect btn blue accent-2" onClick={this.returnToLogs}>Back to logs</a>
</div>
);
}
render(){
if(this.state.render_xml){
return this.renderXml();
} else {
return this.renderTable();
}
}
}
这是父App.js组件
export default class App extends React.Component{
constructor(){
super();
this.state = {
filter: null,
}
this.handleFilterParam = this.handleFilterParam.bind(this);
}
handleFilterParam(filter){
console.log('In parent - handleSearchParam');
console.log(filter);
this.setState({
filter: filter
});
}
render(){
console.log('In parent - render');
console.log(this.state.filter);
return (
<div className="row">
<div className="col s4 l3">
<SideMenu
filterCallback={this.handleFilterParam}
/>
</div>
<div className="col s12 l9">
<Header />
<ResultsTable filter={this.state.filter}/>
</div>
</div>
);
}
}
我仍然对React和ES6很陌生,所以如果其中一些看起来非常业余,请提前道歉。
答案 0 :(得分:0)
如果有人想知道并查看这个问题,我找到了一个非常简单的解决方案。我以前使用过这种生命周期方法,但直到现在还不太了解它。
因此,在我的ResultsTable组件中,我将此代码添加到'listen'以获取新的道具并相应地更新:
componentWillReceiveProps(nextProps) {
if(this.props != nextProps) {
this.props = nextProps;
this.handleResultsTable();
}
}