binarykitten binarykitten - 1 month ago 8
React JSX Question

React component method this.state.myState undefined after returning from child

I am having a Parent component (

BookApplication
) and a child component (
SearchBox
) in React. The SearchBox has an input field, and should give the input back to the parent for handling the event. That is working fine, but when i am back in the parent component in the method
handleSearch
the
this.state...
is undefined.

TypeError: Cannot read property 'books' of undefined


But searchInput has the value it should have.
But i need the books from this.state.books again :/
I understand that in the method
handleSearch
i am working in it's scope, so
this....
is the context of handleSearch... but how do i get the arguments of it's component the
BookApplication
again?
I am still learning javascript, and i thought this shouldnt be a problem, because a function can always use the variables of it's parent object?

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>
);
}


Here also my SearchBox:

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>
);
}


}

Answer

If your question is how to get parent's context from child component, then try

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>
    }
}

And you will get an error here

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

Because this in the callback function not referred to your Component's context. You should keep component's context in variable

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

Finally decision is

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