简体   繁体   中英

When calling a method in a react class component from a react functional component, is the state visible?

I'm building a react application and I'm encountering the following problem:

I have a blog. The blog is implemented with a class component like this:

class Blog extends Component {

    constructor() {
        super();

        this.state = {
            blogPosts: [],
            newPost: {
                title: null,
                body: null
            },
            editPostId: null,
            accessToken: null,
            file: null,
            currentPagePosts: [],
            pageSize: 5
        };

        this.changeHandler = this.changeHandler.bind(this);
        this.submitHandler = this.submitHandler.bind(this);
        this.clearForm = this.clearForm.bind(this);
        this.readMoreClicked.bind(this);

        this.postTitleRef = React.createRef();
        this.postBodyRef = React.createRef();
        this.selectedFileRef = React.createRef();
    }
...
    readMoreClicked(postId) {
        const post = this.state.blogPosts.find(p => p.id === postId);
        post.collapsed = false;
        this.setState({blogPosts: this.state.blogPosts});
    }

    createTable() {
        return this.state.blogPosts.length
            ? <Table
                posts={this.state.currentPagePosts}
                isLoggedIn={!!this.state.accessToken}
                editPost={this.editPost}
                readMoreClicked={this.readMoreClicked} />
            : null;
    }
...
}

The component basically maintains a table of blog posts that looks like this:

在此处输入图像描述

The problem is the read more... links. In the code snippet above, I pass the handler for the read more link to the blog table in createTable(). The Table component is a functional component. It looks like this:

function Table(props) {
...
    return (
...
        <div className="read-more-link-container">
            <span className="read-more-link" onClick={() => props.readMoreClicked(id)}>
                Read more...
            </span>
        </div>
...
    )
}

When someone clicks the read more link, it calls the readMoreClicked() method in the blog component (also in the snippet above). But in the readMoreClicked() method, it tells me the state is not defined:

在此处输入图像描述

This makes me wonder if the state of the blog component won't necessarily come into scope just because you call a method within it from a functional component. <-- Is this the problem? Or is there something else going on?

Thanks.

Try adding a piece of code

super(props) {
   ....
   this.readMoreClicked.bind(this);
   ....
   this.state = {};
}

and define your state on super constructors

I implemented this hack to solve the problem, but it is a hack and I'm still hoping someone can offer a better solution:

First, I added a 'that' prop to the Table component:

    createTable() {
        return this.state.blogPosts.length
            ? <Table
                posts={this.state.currentPagePosts}
                isLoggedIn={!!this.state.accessToken}
                editPost={this.editPost}
                readMoreClicked={this.readMoreClicked}
                that={this} /> // <------------- HERE
            : null;
    }

Second, I pass prop.that to readMoreClicked() from the Table component like this:

<div className="read-more-link-container">
  <span className="read-more-link" onClick={() => props.readMoreClicked(id, props.that)}>
    Read more...
  </span>
</div>

This works. The blog component's state is now available in readMoreClicked() by referencing that.state.

But this is obviously a hack. Does anybody know a better solution?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM