vertically-challenged
@vertically-challenged

Почему React не рендерит компонент при изменении состояния?

В файле UserTable есть функция addRow, изменяющая переменную, отвечающую за количество строк в таблице, но после задания нового состояния рендеринг не происходит, а сама переменная меняется только после второго нажатия на кнопку, вызывающую данную функцию. Я не понимаю, как это исправить.

UserTable:
import React, {Component} from 'react'
import MocData from '../../MocData.json'
import Table from '../../components/Table/Table'

export default class UsersTable extends Component {
    constructor(props) {
        super(props)
        this.state = {
            data: MocData,
            numberOfRows: MocData.length, 
        }
    }

    addRow = (event) => {
        let numberOfRows = this.state.numberOfRows + 1
        this.setState({
            numberOfRows
        })
        console.log(this.state.numberOfRows)
    }

    render() {
        let tableButtons = [
            {
                content: 'Сохранить таблицу', 
                title: null, 
                type: 'save'
            },
            {
                content: 'Добавить запись', 
                title: null, 
                type: 'add',
                onClickHandler: this.addRow
            }
        ]

        return (
            <Table
                numberOfRows = {this.state.numberOfRows}
                numberOfColumns = {Object.keys(this.state.data[0].data).length}
                columnNames = {Object.keys(this.state.data[0].data)}
                content = {this.state.data}
                tableButtons = {tableButtons}
            />      
        )
    }
}


Table.js:
Здесь в функции createRow() используется значения переменной numberOfRows, она передается первым параметром
import React, {Component} from 'react'
import './Table.scss'
import Row from './Parts/Row'
import Button from '../Button/Button'

export default class Table extends Component {
    constructor(props) {
        super(props)
        this.state = {
            numberOfRows: props.numberOfRows, // Число от 0
            numberOfColumns: props.numberOfColumns, // Число от 0
            columnNames: props.columnNames, // Массив строк, например ['Имя1','Имя2']
            content: props.content, // Массив объектов, каждый из которых содержит id и объект data | { id: 1234, data: {name: 'Иван', surname:'Иванов'}}
            tableButtons: props.tableButtons, // Массив объектов с параметрами кнопок, где каждый объект содержит параметры конкретной кнопки
            rowButtons: []
        }
    }

    createButtons = (tableButtons) => {
        let Buttons = []

        tableButtons.map( (item, index) => {
            Buttons.push(
                <Button
                    key = {tableButtons[index].content}
                    title = {tableButtons[index].title}
                    type = {tableButtons[index].type}
                    onClick = {tableButtons[index].onClickHandler}
                >
                    {tableButtons[index].content}
                </Button>        
            )
        })

        return Buttons
    }

    createRow = (counter, content, isHeader = false) => {
        let rows = []
        for (let i = 0; i < counter; i++) {
            if (isHeader) {
                rows.push(
                    <Row
                        key = {counter}
                        numberOfColumns = {this.state.numberOfColumns}
                        content = {content}
                        isHeader = {isHeader}
                    />) 
            } else if (content[i]){
                rows.push(
                    <Row
                        key = {content[i]._id}
                        id = {content[i]._id}
                        numberOfColumns = {this.state.numberOfColumns}
                        content = {content[i].data}
                        isHeader = {isHeader}
                    />) 
            } else {
                rows.push(
                    <Row
                        key = {counter + 1}
                        numberOfColumns = {this.state.numberOfColumns}
                        content = {null}
                        isHeader = {isHeader}
                    />) 
            }
        }
        return (rows)
    }

    render() {
        return (
            <React.Fragment>
                <table className="Table">
                    <tbody>
                        {this.createRow(1, this.state.columnNames, true)}
                        {this.createRow(this.state.numberOfRows, this.state.content)}
                    </tbody>
                </table> 
                <div className="buttonContainer">
                    {this.createButtons(this.state.tableButtons)}
                </div>
            </React.Fragment>
        )
    }
}


Button.js:
import React from 'react'
import './Button.scss'

const Button = props => {
    const cls = `Button ${props.type}`
    return (
        <button 
            className={cls}
            type="button"
            onClick={props.onClick}
            title={props.title}
        >
            <span>{props.children}</span>
        </button>
    )
}

export default Button
  • Вопрос задан
  • 719 просмотров
Решения вопроса 1
Aetae
@Aetae
Тлен
У тебя в Table render используется this.state.numberOfRows, а должно this.props.numberOfRows. this.state.numberOfRows ты задаёшь только один раз при создании(constructor) и никогда не меняешь.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы