Задать вопрос
@Worddoc
Frontend explorer

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

Проблема в том, что компонент Form, некоторые элементы которого зависят от стейта - не ререндерятся. В devtools react видно, что стейт меняется нормально. В чем может быть проблема?

Код
class Row extends React.Component {
    constructor(props) {
        super(props)
        this.removeClickHandler = this.props.removeClickHandler;
        this.changeClickHandler = this.props.changeClickHandler;
    }

    render() {

        return (
            <tr className="app__row">
                <td className="app__cell app__cell--name">{this.props.name}</td>
                <td className="app__cell app__cell--phone">{this.props.phone}</td>
                <td className="app__cell app__cell--action">
                    <button 
                        className="app__cellButton btn"
                        onClick={this.removeClickHandler}>REMOVE
                    </button>
                    <button 
                        className="app__cellButton btn"
                        onClick={this.changeClickHandler}>CHANGE
                    </button>
                </td>
            </tr>
        );
    }
}

class Table extends React.Component {
    constructor(props) {
        super(props)

    }

    makeRows() {
        return this.props.people.map((item,index) => {
            return <Row 
                    name={item.name} 
                    key={index}
                    phone={item.phone} 
                    removeClickHandler={this.props.removeClickHandler}
                    changeClickHandler={this.props.changeClickHandler}/>
        })
    }

    render() {
        return (

            <table>
                <thead>
                    <tr>
                        <th>Name</th>
                        <th>Phone</th>
                        <th>Action</th>
                    </tr>
                </thead>
                <tbody>
                    {this.makeRows()}
                </tbody>
            </table>
        )
    }
}

class Form extends React.Component {
    constructor(props) {
        super(props)
        this.onClickHandler = this.props.onClickHandler;
        this.onPutInputHandler = this.props.onPutInputHandler;
        this.isFormStateChange = this.props.isFormStateChange;
    }


    render() {
        return (
            <React.Fragment>
                <input 
                    className="app__nameInput"
                    type="text"
                    data-type="name"
                    value={this.props.nameValue}
                    onChange={this.onPutInputHandler}
                    placeholder={this.isFormStateChange === false ? "Type a name..." : ""}/>
                <input 
                    className="app__phoneInput"
                    type="text"
                    data-type="phone"
                    value={this.props.phoneValue}
                    onChange={this.onPutInputHandler}
                    placeholder={this.isFormStateChange === false ? "Type a phone..." : ""}/>
                <input 
                    className="app__submitButton btn"
                    value={this.isFormStateChange === false ? "ADD" : "SAVE CHANGES"}
                    type="submit"
                    onClick={this.onClickHandler}/>
            </React.Fragment>
        )
    }
}


class App extends React.Component {
	constructor(props) {
		super(props);
		
		let people = [
			{
				name: 'John',
				phone: '+7(915)5554522'
			},
			{
				name: 'Chinda',
				phone: '+7(915)5552565'
			},
			{
				name: 'Mike',
				phone: '+7(915)6546546'
			},
			{
				name: 'Lara',
				phone: '+7(915)8793453'
			},
			{
				name: 'Borines',
				phone: '+7(915)6456325'
			},
			{
				name: 'Maria',
				phone: '+7(915)8673453'
			}
		]

		this.state = {
			data: people,
			inputName: '',
			inputPhone: '',
			isFormStateChange: false
		}

		this.onPutInputHandler = this.onPutInputHandler.bind(this);
		this.onClickHandler = this.onClickHandler.bind(this);
		this.removeClickHandler = this.removeClickHandler.bind(this);
		this.changeClickHandler = this.changeClickHandler.bind(this);
	}

	onClickHandler(e) {
		e.preventDefault();
		if (this.state.inputName.length <= 0 || this.state.inputPhone.length <= 0) return;
		this.setState(prev => ({
			data: prev.data.concat([{
				name: this.state.inputName,
				phone: this.state.inputPhone
			}]),
			inputName: '',
			inputPhone: ''
		}))
	}

	onPutInputHandler(e) {
		let input = e.target;

		e.preventDefault();
		if (input.dataset.type === 'name') {
			this.setState({inputName: input.value})
		} else if (input.dataset.type === 'phone') {
			this.setState({inputPhone: input.value});
		}

	}

	removeClickHandler(e) {
		let personData = {
			name: e.currentTarget.parentElement.parentElement.querySelector('.app__cell--name').innerHTML,
			phone: e.currentTarget.parentElement.parentElement.querySelector('.app__cell--phone').innerHTML
		};
		this.setState((prev) => ({
			data: prev.data.filter((item) => {
				if (item.name === personData.name && item.phone === personData.phone) return false;
				return item;
			})
		}));
	}

	changeClickHandler(e) {
		let person = {
			name: e.currentTarget.parentElement.parentElement.querySelector('.app__cell--name').innerHTML,
			phone: e.currentTarget.parentElement.parentElement.querySelector('.app__cell--phone').innerHTML
		}
		this.setState({isFormStateChange: true})
	}

	render() {
		return (
			<div>
				<Form 
					onClickHandler={this.onClickHandler}
					onPutInputHandler={this.onPutInputHandler}
					nameValue={this.state.inputName}
					phoneValue={this.state.inputPhone}
					isFormStateChange={this.state.isFormStateChange}/>

				<Table 
				people={this.state.data}
				removeClickHandler={this.removeClickHandler}
				changeClickHandler={this.changeClickHandler}/>
			</div>
		)
	}
}


ReactDOM.render(<App />, document.querySelector('.app'));
  • Вопрос задан
  • 289 просмотров
Подписаться 1 Простой 2 комментария
Решения вопроса 1
0xD34F
@0xD34F Куратор тега React
Проблема в том, что компонент Form, некоторые элементы которого зависят от стейта - не ререндерятся.

"Некоторые" - это, видимо, инпуты (плейсхолдеры) и кнопка (текст). Почему не обновляются - да потому, что значение isFormStateChange формы, от которого они зависят (кстати, не "от стейта" - стейта у вас там нет, что за бред-то?), устанавливается лишь единожды, в конструкторе, и изменение isFormStateChange родительского компонента никак на него не влияет.

Я так понимаю, вы стремились к чему-то такому?
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

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

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