Метод компонента React this.state.MyState не определен после возврата из дочернего элемента

#javascript #reactjs

#javascript #reactjs

Вопрос:

У меня есть родительский компонент ( BookApplication ) и дочерний компонент ( SearchBox ) в React. Поле поиска имеет поле ввода и должно возвращать входные данные родительскому элементу для обработки события. Это работает нормально, но когда я возвращаюсь в родительский компонент в методе, handleSearch this.state... не определено.

 TypeError: Cannot read property 'books' of undefined
  

Но searchInput имеет значение, которое он должен иметь.
Но мне снова нужны книги из this.state.books :/
Я понимаю, что в методе, handleSearch с которым я работаю, это область видимости, поэтому this.... контекст handleSearch… но как мне снова получить аргументы этого компонента BookApplication ?
Я все еще изучаю javascript, и я подумал, что это не должно быть проблемой, потому что функция всегда может использовать переменные своего родительского объекта?

 class BookApplication extends React.Component {

    constructor() {
        super();
        this.state = {books: []};
    }

    componentDidMount() {
        $.get(PATH, function (result) {
            this.setState({
                books: result
            });
        }.bind(this));
    }

    handleSearch(searchInput) {
        //Sort the books list
        var sortedList = [];
        this.state.books.map(
            function (currentBook) {
                currentBook.keys().forEach(
                    function (key, pos) {
                        if (key.contains(searchInput)) {
                            sortedList.push(currentBook)
                        }
                    }
                )
            }
        );
    }

render() {
        return (
            <div>
                <SearchBox onSearch={this.handleSearch}/>
                <div className="book-list">
                    {this.state.books.map(function (currentBook) {
                        return <Book book={currentBook} key={currentBook.id}/>;
                    }) }
                </div>
            </div>
        );
    }
  

Здесь также мое поле поиска:

 class SearchBox extends React.Component {
constructor(props) {
    super(props);
    this.state = {searchFieldInput: ''};
    this.handleSearchChange = this.handleSearchChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
}

handleSearchChange(event) {
    this.setState({searchFieldInput: event.target.value});
}

handleSubmit(e) {
    //Prevent the browser's defeault action of submitting the form
    e.preventDefault();

    var searchFieldInput = this.state.searchFieldInput.trim();
    //Call the passed callback function
    this.props.onSearch({searchFieldInput: searchFieldInput});
}

render() {
    return (
        <div className="book-search">
            <input
                type="text"
                value={this.state.searchFieldInput}
                onChange={this.handleSearchChange}
                placeholder="Search..."
                className="search-bar"
            />
            <button onClick={this.handleSubmit} className="search-button">Search</button>
        </div>
    );
}
  

}

Комментарии:

1. похоже, что кто-то напрямую манипулирует состоянием, а не setState

2. я работал с самим facebook tutorial ! 😀

Ответ №1:

Если ваш вопрос заключается в том, как получить родительский контекст из дочернего компонента, то попробуйте

 class ParentComponent extends React.Component {
    ...
    ...
    clickHandler(event){}

    render(){
        <ChildComponent parent={this}/>
    }
}

class ChildComponent extends React.Component {
    constructor(props){
        super(props);
    }

    render(){
        let parent = this.props.parent;
        return <button onClick={parent.clickHandler}></button>
    }
}
  

И здесь вы получите сообщение об ошибке

 componentDidMount() {
    $.get(PATH, function (result) {
        this.setState({
            books: result
        });
    }.bind(this));
}
  

Потому что this в функции обратного вызова не ссылаются на контекст вашего компонента. Вы должны сохранить контекст компонента в переменной

 componentDidMount() {
    let self = this;
    $.get(PATH, function (result) {
        self.setState({
            books: result
        });
    }.bind(this));
}
  

Наконец, решение

 constructor(props) {
    super(props);
    this.state = {books: []};
    //add the following line into your code
    this.handleSearch = this.handleSearch.bind(this);
}
  

Комментарии:

1. нет, я уже вернулся в родительский компонент в его методе handleSearch с вводом дочернего компонента. Но родительское состояние, похоже, больше не доступно. Мне снова нужен this.state.books тот, который я загрузил в начале.

2. Но я не получаю ошибку в методе componentDidMount… ОСТАЛЬНОЕ работает абсолютно нормально. Когда мое приложение запускается, я загружаю книги и показываю их (с помощью this.state.books). Это работает без проблем. Затем я пишу строку для поиска в моем вложенном поле ввода (SearchComponent). Когда я возвращаюсь из компонента поиска обратно в родительский компонент, я не могу снова получить книги из this.state.books

3. Добавьте следующую строку this.handleSearch = this.handleSearch.bind(this) в свой constructor