簡體   English   中英

子組件只會在父組件的按鈕提交被點擊兩次時重新渲染

[英]Child component will only re-render when Parent component's button, Submit, is clicked twice

我有兩個組件遇到了這個問題。 父組件 CustomerTableTools 將表(頁面)的大小發送到子組件 (FetchCustomerTable)。 當我單擊提交時,父級的狀態會改變,但除非我單擊提交兩次,否則子級不會重新渲染。 輸入和提交按鈕在父級內部,表格在子級內部。 我在這里遺漏了一個重要的細節嗎? 我認為如果 Parent 將其狀態作為道具發送給 Child 並且狀態發生變化,則應該重新渲染 Child 。

該表的數據由 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

好的,這是給正在閱讀本文的人。 我能夠通過刪除多余的不必要狀態“值”來解決我的問題。 我做了一個 FormControl 選擇,讓用戶從預定義的頁面大小列表中進行選擇,而不是輸入頁面大小。 這個選擇器的名字是'limit',它與代表頁面大小的狀態同名。 我有一個處理程序,只要選擇了 select 中的一個選項,它就會更新此狀態。

你可以使用componentWillReceiveProps的作出反應,從生命周期的Child組件。
https://developmentarc.gitbooks.io/react-indepth/content/life_cycle/update/component_will_receive_props.html

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM