Я новичок в React и работаю над приложением MERN Stack. Я включил react-data-grids
в свое приложение. Я использую axios
для извлечения данных строк. Я создал систему разбиения на страницы, поэтому, когда пользователь прокручивает до конца таблицы данных, код выбирает новые строки и добавляет их в состояние компонента. Компонент ReactDataGrid использует строки из состояния.
Теперь мой вопрос заключается в том, почему ReactDataGrid не выполняет повторный рендеринг, несмотря на добавление строк в состояние.
Родительский компонент (Table.jsx)
import React from 'react'
import RDGView from 'components/RDGView/RDGView.jsx'
import {
Card,
CardHeader,
CardBody,
CardFooter,
CardTitle,
Row,
Col,
Alert
} from 'reactstrap'
import Stats from 'components/Stats/Stats.jsx'
import { PulseLoader } from 'react-spinners'
import { css } from '@emotion/core'
import API from 'config/API'
import 'views/Table/Table.scss'
const override = css`
display: block;
margin: 0 auto;
border-color: red;
padding: 1rem;
text-align: center;
`
class Table extends React.Component {
state = {
loading: true,
error: '',
table: {},
rows: [],
tableFound: false,
page: 0,
count: null
}
loadNextPage = () => {
if (
this.state.count === null ||
this.state.rows.length < this.state.count
) {
API.get(`/tables/${this.props.match.params.id}?page=${this.state.page}`)
.then(res => res.data)
.then(data => {
// Format data
this.setState({
loading: false,
table: data.data.table,
tableFound: true,
page: this.state.page + 1,
count: data.data.count
})
this.setState(state => {
let rows = state.rows
rows = rows.concat(data.data.rows)
console.log(rows)
return { rows }
})
})
.catch(err => {
let error = 'Unknown Error'
if (typeof err.response !== 'undefined') {
if (typeof err.response.data.message !== 'undefined') {
error = err.response.data.message
}
}
this.setState({
error,
loading: false
})
})
}
}
createTable = () => {
console.log('Cilcked!')
}
componentWillMount() {
// Get all the Table
this.loadNextPage()
}
onGridRowsUpdated = (fromRow, toRow, updated) => {
// Update rows at the DB side
API.put(`tables/${this.state.table._id}`, {
row: this.state.rows[fromRow]._id,
updated
})
.then(res => res.data)
.then(data => {})
.catch(err => {
let error = ''
if (typeof err.response.data.message !== 'undefined') {
error = err.response.data.message
} else {
error = 'Unknown error updating table'
}
this.setState({
error
})
})
this.setState(state => {
const rows = state.rows.slice()
rows[fromRow].values = { ...rows[fromRow].values, ...updated }
return { rows }
})
}
addRow() {
// Add a new Row
let newRow = {
values: {}
}
let columns = this.state.table.columns
let lastRow = this.state.rows[this.state.rows.length - 1]
columns.map(column => {
newRow.values[column.key] = column.editable
? ' '
: lastRow.values[column.key]
})
newRow.values.id = lastRow.values.id + 1
API.post(`/rows/${this.state.table._id}`, { row: newRow })
.then(res => res.data)
.then(data => {
this.setState(state => {
let rows = state.rows
rows.push(newRow)
return { rows }
})
})
.catch(err => {
let error = 'Unknown Error'
if (typeof err.response !== 'undefined') {
if (typeof err.response.data.message !== 'undefined') {
error = err.response.data.message
}
}
this.setState({
error,
loading: false
})
})
}
deleteTable(table) {
if (window.confirm(`Are you sure to delete ${table.name}`)) {
API.delete(`/tables/${table._id}`)
.then(res => res.data)
.then(data => {
window.location = '../tables'
})
.catch(err => {
this.setState({
error: err.response
? err.response.data.message || 'Unknown Error'
: 'Unknown Error'
})
})
}
}
render() {
return (
<div className="content">
{this.state.loading ? (
<PulseLoader
css={override}
sizeUnit={'rem'}
size={1.6}
color={'#000'}
loading={this.state.loading}
/>
) : (
<React.Fragment>
{this.state.error ? (
<Alert color="danger">{this.state.error}</Alert>
) : (
''
)}
<Row>
{this.state.tableFound && this.state.rows.length ? (
<React.Fragment>
<RDGView
rows={this.state.rows}
table={this.state.table}
onGridRowsUpdated={this.onGridRowsUpdated}
addRow={this.addRow.bind(this)}
deleteTable={this.deleteTable.bind(this)}
loadNextPage={this.loadNextPage.bind(this)}
/>
</React.Fragment>
) : (
<Alert color="danger">Table not found</Alert>
)}
</Row>
</React.Fragment>
)}
</div>
)
}
}
export default Table
Дочерний компонент: (RDGView.jsx)
import React from 'react'
import { findDOMNode } from 'react-dom'
import PropTypes from 'prop-types'
import ReactDataGrid from 'react-data-grid'
class RDGView extends React.Component {
constructor(props) {
super(props)
this.canvas = null
this.scrollListener = () => {
if (
this.canvas.scrollHeight -
(this.canvas.scrollTop + this.canvas.clientHeight) <
10
) {
this.props.loadNextPage()
}
}
}
state = {
rows: this.props.rows,
columns: this.props.table.columns
}
onGridRowsUpdated = ({ fromRow, toRow, updated }) => {
this.props.onGridRowsUpdated(fromRow, toRow, updated)
}
componentDidMount() {
this.canvas = findDOMNode(this).querySelector('.react-grid-Canvas')
this.canvas.addEventListener('scroll', this.scrollListener)
}
componentWillUnmount() {
if (this.canvas) {
this.canvas.removeEventListener('scroll', this.scrollListener)
}
}
componentDidUpdate(props, newProps) {
if (this.state.rows !== newProps.rows) {
this.setState({
columns: props.table.columns,
rows: props.rows
})
}
}
render() {
return (
<React.Fragment>
<ReactDataGrid
columns={this.state.columns}
rowGetter={i => {
if (i < 0) {
i = 0
}
return this.state.rows[i].values
}}
rowsCount={this.state.rows.length}
minHeight={`20vh`}
onGridRowsUpdated={this.onGridRowsUpdated.bind(this)}
/>
<div className="container">
<div className="jumbotron bg-transparent text-center">
<div className="btn-group">
<button
className="btn btn-danger"
onClick={() => this.props.deleteTable(this.props.table)}
>
Delete Table
</button>
<button className="btn btn-warning">Reset Table</button>
</div>
</div>
</div>
</React.Fragment>
)
}
}
RDGView.propTypes = {
rows: PropTypes.array,
table: PropTypes.object,
onGridRowsUpdated: PropTypes.func,
addRow: PropTypes.func,
deleteTable: PropTypes.func,
loadNextPage: PropTypes.func
}
export default RDGView
Может кто-нибудь помочь с этим? Как я могу заставить его перерисоваться, когда строки обновляются. Спасибо!