Reactjs 仅当父组件';s按钮“提交”被单击两次
我有两个组件,我有这个问题。父组件CustomerTableTools将表(页面)的大小发送给子组件(FetchCustomerTable)。当我单击“提交”时,父对象的状态将更改,但除非我单击“提交”两次,否则子对象将不会重新渲染。输入和提交按钮位于父级内部,表位于子级内部。我遗漏了一个重要的细节吗?我认为如果父对象将其状态作为道具发送给子对象,并且状态发生了变化,则子对象应该重新渲染 表的数据由this.props.customers填充 谢谢大家抽出时间。我只想学习,我感谢你的投入,谢谢Reactjs 仅当父组件';s按钮“提交”被单击两次,reactjs,jsx,Reactjs,Jsx,我有两个组件,我有这个问题。父组件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
//***************************
//CustomerTableTools(父级):
//****************************
从“React”导入React,{Component};
从“./FetchCustomerTable”导入FetchCustomerTable
从“../Util/LoadingSpinner”导入LoadingSpinner
从“../Util/ErrorStatus”导入ErrorStatus
从“axios/index”导入axios;
类CustomerTableTools扩展组件{
建造师(道具){
超级(道具);
此.state={
错误:,
页码:0,
限额:10,
数值:10,
客户:[],
};
this.handleChange=this.handleChange.bind(this);
this.handleSubmit=this.handleSubmit.bind(this);
log(“props:+JSON.stringify(props))
}
手变(活动){
如果(event.target.value>=0&(!isNaN(event.target.value)&&
(函数(x){return(x | 0)==x;})(parseFloat(event.target.value))){
this.setState({value:event.target.value});
}
}
componentDidMount(){
this.setState({limit:this.state.value,limitChanged:true});
log(“获取数据1”);
this.setState({loading:true,statusMessage:});
axios.get(“http://localhost:8090/customer/viewCustomers/", {
参数:{
页面:this.state.page,
限制:this.state.limit
}
})
。然后(响应=>{
//log(“响应:+JSON.stringify(response.data));
这是我的国家({
客户:response.data.content,
statusMessage:null,
加载:错误
});
console.log(this.state.customers);
})
.catch(错误=>{
console.log(错误);
这是我的国家({
状态消息:,
})
}
);
}
handleSubmit(事件){
event.preventDefault();
this.setState({limit:this.state.value,limitChanged:true});
console.log(“==HANDLE SUBMIT===”);
this.setState({loading:true,statusMessage:});
axios.get(“http://localhost:8090/customer/viewCustomers/", {
参数:{
页面:this.state.page,
限制:this.state.limit
}
})
。然后(响应=>{
//log(“响应:+JSON.stringify(response.data));
这是我的国家({
客户:response.data.content,
statusMessage:null,
加载:错误
});
console.log(this.state.customers);
})
.catch(错误=>{
console.log(错误);
这是我的国家({
状态消息:,
})
}
);
}
render(){
设tableBody=null;
表体=
返回(
页面大小:
{表体}
);
}
}
导出默认CustomerTableTools
//***************************
//FetchCustomerTable(子项):
//***************************
从“React”导入React,{Component};
从“axios”导入axios;
导入“../App.css”
从“../Util/LoadingSpinner”导入LoadingSpinner
从“../Util/ErrorStatus”导入ErrorStatus
从“react-react”导入{BootstrapTable,TableHeaderColumn,ClearSearchButton}
引导表';
从“react bootstrap”导入{按钮,Glyphicon}
类FetchCustomerTable扩展组件{
onAfterSaveCell(行){
const customerId=行['customerId'];
axios({
方法:'放',
网址:`http://localhost:8090/customer/updateCustomer/${customerId}`,
数据:JSON.stringify(行),
标题:{'Content-Type':'application/json;charset=utf-8'}
})
。然后((响应)=>{
控制台日志(响应);
console.log(response.data);
})
.catch((错误)=>{
console.log(错误);
//记录器错误(error);
});
}
handleDeletedRow(行键){
log(“删除的键:+rowKeys”);
axios({
方法:“删除”,
网址:`http://localhost:8090/customer/deleteCustomers/${rowKeys}`,
数据:行键,
标题:{'Content-Type':'application/json;charset=utf-8'}
})
。然后((响应)=>{
控制台日志(响应);
console.log(response.data);
})
.catch((错误)=>{
console.log(错误);
//记录器错误(error);
});
}
//表格顶部的样式删除按钮
customDeleteButton=(onBtnClick)=>{
返回(
删除
挑选出来的
);
}
onSearchChange=(搜索文本)=>{
log(“内部搜索更改!”);
this.setState({searchText:searchText});
}
handleClearButtonClick=(onClick)=>{
如果(!!this.state.searchText){
log(“获取数据2”);
//this.setState({loading:true,statusMessage:});
axios.get(“http://localhost:8090/customer/searchResults/", {
参数:{
名字:this.state.searchText,
电子邮件:this.state.searchText,
佩奇:这是道具