我遇到两个问题。父组件CustomerTableTools将表(页面)的大小发送到子组件(FetchCustomerTable)。当我单击“提交”时,“父”状态将发生变化,但是除非再次单击“提交”,否则子级将不会重新渲染。输入和“提交”按钮位于父级内部,表位于子级内部。我在这里错过了重要的细节吗?我认为如果父母将其状态作为道具发送给孩子并且状态发生变化,则应该重新渲染孩子。
该表的数据由this.props.customers填充 谢谢大家的宝贵时间。我只想学习,感谢您的投入。
//***************************
//CustomerTableTools (Parent):
//****************************
import React, { Component } from 'react';
import FetchCustomerTable from './FetchCustomerTable'
import LoadingSpinner from '../Util/LoadingSpinner'
import ErrorStatus from '../Util/ErrorStatus'
import axios from "axios/index";
class CustomerTableTools extends Component {
constructor(props) {
super(props);
this.state = {
limitChanged: false,
page: 0,
limit: 10,
value: 10,
customers: [],
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
console.log("props: "+JSON.stringify(props))
}
handleChange(event) {
if(event.target.value >= 0 && (!isNaN(event.target.value) &&
(function(x) { return (x | 0) === x; })(parseFloat(event.target.value)))) {
this.setState({value: event.target.value});
}
}
componentDidMount() {
this.setState({limit: this.state.value, limitChanged: true});
console.log("Fetching data1");
this.setState({loading: true, statusMessage: <LoadingSpinner/>});
axios.get("http://localhost:8090/customer/viewCustomers/", {
params: {
page: this.state.page,
limit: this.state.limit
}
})
.then(response => {
// console.log("response: "+JSON.stringify(response.data));
this.setState({
customers: response.data.content,
statusMessage: null,
loading: false
});
console.log(this.state.customers);
})
.catch(error => {
console.log(error);
this.setState({
statusMessage: <ErrorStatus error={error.toString()}/>,
})
}
);
}
handleSubmit(event) {
event.preventDefault();
this.setState({limit: this.state.value, limitChanged: true});
console.log("=====HANDLE SUBMIT=====");
this.setState({loading: true, statusMessage: <LoadingSpinner/>});
axios.get("http://localhost:8090/customer/viewCustomers/", {
params: {
page: this.state.page,
limit: this.state.limit
}
})
.then(response => {
// console.log("response: "+JSON.stringify(response.data));
this.setState({
customers: response.data.content,
statusMessage: null,
loading: false
});
console.log(this.state.customers);
})
.catch(error => {
console.log(error);
this.setState({
statusMessage: <ErrorStatus error={error.toString()}/>,
})
}
);
}
render() {
let tableBody = null;
tableBody = <FetchCustomerTable customers={this.state.customers}/>
return(
<div>
<div id="grid">
<div id="item2">
<form style={{ position: 'absolute', bottom: 0}}
onSubmit={this.handleSubmit}>
<label>
<div>Page Size:</div>
<input style={{width: '7vh'}} type="number"
value={this.state.value} onChange=
{this.handleChange} />
</label>
<input type="submit" value="Submit" />
</form>
</div>
</div>
{tableBody}
</div>
);
}
}
export default CustomerTableTools
//***************************
//FetchCustomerTable (Child):
//***************************
import React, { Component } from 'react';
import axios from 'axios';
import '../../App.css'
import LoadingSpinner from '../Util/LoadingSpinner'
import ErrorStatus from '../Util/ErrorStatus'
import {BootstrapTable, TableHeaderColumn, ClearSearchButton} from 'react-
bootstrap-table';
import {Button, Glyphicon} from 'react-bootstrap'
class FetchCustomerTable extends Component {
onAfterSaveCell(row) {
const customerId = row['customerId'];
axios({
method: 'PUT',
url: `http://localhost:8090/customer/updateCustomer/${customerId}`,
data: JSON.stringify(row),
headers:{'Content-Type': 'application/json; charset=utf-8'}
})
.then((response) => {
console.log(response);
console.log(response.data);
})
.catch((error) => {
console.log(error);
//logger.error(error);
});
}
handleDeletedRow(rowKeys) {
console.log("KEYS DROPPED: "+ rowKeys);
axios({
method: 'DELETE',
url: `http://localhost:8090/customer/deleteCustomers/${rowKeys}`,
data: rowKeys,
headers:{'Content-Type': 'application/json; charset=utf-8'}
})
.then((response) => {
console.log(response);
console.log(response.data);
})
.catch((error) => {
console.log(error);
//logger.error(error);
});
}
//Style delete button on top of table
customDeleteButton = (onBtnClick) => {
return (
<Button onClick={ onBtnClick }><Glyphicon glyph="remove" /> Delete
Selected</Button>
);
}
onSearchChange = (searchText) => {
console.log("inside search change!");
this.setState({searchText: searchText});
}
handleClearButtonClick = (onClick) => {
if(!!this.state.searchText) {
console.log("Fetching data2");
//this.setState({loading: true, statusMessage: <LoadingSpinner/>});
axios.get("http://localhost:8090/customer/searchResults/", {
params: {
firstName: this.state.searchText,
email: this.state.searchText,
page: this.props.page,
limit: this.props.limit,
}
})
.then(response => {
console.log("respsonse:
"+JSON.stringify(response.data.pageable));
this.setState({
//loading: false,
customers: response.data.content,
statusMessage: null
})
console.log(this.state.customers);
})
.catch(error => {
console.log(error);
this.setState({
statusMessage: <ErrorStatus error=
{error.toString()}/>,
})
}
);
onClick();
} else {
//TODO: add method to clear search results
}
}
createCustomClearButton = (onClick) => {
return (
<ClearSearchButton
btnText='Submit'
btnContextual='btn-warning'
className='my-custom-class'
onClick={ e => this.handleClearButtonClick(onClick) }/>
);
}
render() {
let content = null;
//settings for BootStrapTable
const options = {
defaultSortName: 'customerId', // default sort column name
defaultSortOrder: 'asc', // default sort order
afterDeleteRow: this.handleDeletedRow,
deleteBtn: this.customDeleteButton,
onSearchChange: this.onSearchChange,
clearSearch: true,
clearSearchBtn: this.createCustomClearButton,
pagination: true,
nextPage: 'Next',
};
const selectRow = {
mode: 'checkbox'
};
const cellEditProp = {
mode: 'dbclick',
blurToSave: true,
afterSaveCell: this.onAfterSaveCell // a hook for after saving
cell
};
const fetchInfo = {
dataTotalSize: 100, // or checkbox
};
content =
<div className="tableContainer">
<BootstrapTable remote={ true } search={ true } striped
bordered condensed hover headerStyle={{ fontFamily: 'proxima-
nova' }}
bodyStyle={{ fontFamily: 'proxima-nova' }}
data={ this.props.customers } options={ options }
cellEdit={ cellEditProp } selectRow={selectRow} deleteRow>
<TableHeaderColumn name='customerId' dataField='customerId'
isKey dataSort>Customer ID</TableHeaderColumn>
<TableHeaderColumn name='lastName' dataField='lastName'
dataSort>Last Name</TableHeaderColumn>
<TableHeaderColumn name='firstName' dataField='firstName'
dataSort>First Name</TableHeaderColumn>
<TableHeaderColumn name='email' dataField='email'
dataSort>Email</TableHeaderColumn>
<TableHeaderColumn name='address' dataField='address'
dataSort>Address</TableHeaderColumn>
<TableHeaderColumn name='city' dataField='city'
dataSort>City</TableHeaderColumn>
<TableHeaderColumn name='state' dataField='state'
dataSort>State</TableHeaderColumn>
<TableHeaderColumn name='zip' dataField='zip'
dataSort>Zip</TableHeaderColumn>
<TableHeaderColumn name='lastEmailSent'
dataField='lastEmailSent' dataSort editable={ false }>Last Email
Sent</TableHeaderColumn>
</BootstrapTable>
</div>
return(
<div>
<div className="center">
{content}
</div>
</div>
);
}
}
export default FetchCustomerTable
答案 0 :(得分:1)
好吧,这是给正在阅读本文的人的。我可以通过删除多余的不必要的状态“值”来解决我的问题。我选择了FormControl,并让用户从预定义页面大小的列表中进行选择,而不是键入页面大小。该选择器的名称为“ limit”,与表示页面大小的状态名称相同。我有一个处理程序,只要选择了select中的一个选项,便会更新此状态。
答案 1 :(得分:0)
您可以在componentWillReceiveProps
组件的React生命周期中使用Child
。
https://developmentarc.gitbooks.io/react-indepth/content/life_cycle/update/component_will_receive_props.html