React - What is lifting state up?
React follows flux architectural pattern, meaning the data flows in only one direction.
All react components are built in the same way. Data flows in only one direction.
Imagine we have a component tree like below (before lifting state Up):
As per above component tree, if user is purchasing some books, then we need to share that information with Purchase component so user can provide the confirmation.
Booklist and Purchase are siblings in the above component tree without any direct association between them. If we want to share the list of books that user has purchased then as per current implementation, there is no way to do so.
All we need is to make sure that Purchase has access to the books which user has selected.
As books selected by user are maintained in the BookList's local state, which is a private information and Purchase can't access that information in any way.
In order to solve this problem, what if we move the selected books information to root component of this tree, i.e. Library?
As Library is parent to both the BookList and Purchase components, it can control data passed to them. Also, BookList and Purchase will have access to exposed information and methods of Library automatically.
After Lifting State Up:
Refer below code for reference:
import React from "react";
import ReactDOM from "react-dom";
import "./css/my-app.css";
import "./css/book.css";
//BookList Child 2
class BookAuthor extends React.Component {
render() {
const { title, author, description, special } = this.props;
return (
<>
<section>
<h1 className={special ? "book-title special" : "book-title"}>
{title}
</h1>
<h4 className="bok-author">{author}</h4>
<p className="description">{description}</p>
<button className="btn" onClick={this.props.buyBook}>
Buy this Book!
</button>
</section>
</>
);
}
}
//BookList Child 1
class BookImage extends React.Component {
render() {
const coverImage = this.props.coverImage;
return (
<img
src={coverImage}
alt="Book Cover"
style={{ maxHeight: 300, maxWidth: 300 }}
></img>
); //inlline
}
}
// Child 1 (Sibling 1)
class BookList extends React.Component {
render({ book, buyBook } = this.props) {
return (
<>
<article className="book">
<BookImage coverImage={book.coverImage} />
<BookAuthor {...book} buyBook={() => buyBook(book.id)}></BookAuthor>
</article>
</>
);
}
}
//Child 2 (Sibling 2)
class Purchase extends React.Component {
render({ purchasedBooks, books } = this.props) {
return (
<>
{/* Display purchased books if available */}
<div>
<h2
style={{
color: "white",
backgroundColor: "rgba(0, 0, 0, 0.6)",
}}
>
{purchasedBooks.length > 0
? "You have bought below books: "
: "You have not bought any book yet!"}
</h2>
</div>
<section className="booklist">
{purchasedBooks.map((bookId) => {
//reusing existing component again!
return <BookList book={books.find((book) => book.id === bookId)} />;
})}
</section>
</>
);
}
}
//Parent
class BookLibrary extends React.Component {
constructor() {
super();
//moving state Up!
this.state = {
purchasedBooks: [],
};
}
render() {
const books = [
{
id: 3,
title: "The Alchemist",
author: "Paulo Cohlo",
coverImage: "./images/the-alchemist.jpg",
},
{
id: 4,
title: "Grandma's Bag of Stories",
author: "Sudha Murthy",
coverImage: "./images/grandams-bag-of-stories.jpg",
},
{
id: 5,
title: "The Power of Your Subconscious Mind",
author: "Joseph Murphy",
coverImage: "./images/the-power-of-your-subconscious-mind.jpg",
special: true,
},
];
const buyBook = (bookId) => {
this.state.purchasedBooks.push(bookId);
this.setState({ purchasedBooks: this.state.purchasedBooks });
};
return (
<>
<section className="booklist">
{books.length > 0 ? (
books.map((book) => (
<BookList buyBook={buyBook} key={book.id} book={book} />
))
) : (
<h2>Sorry, currently we have no books in our library.</h2>
)}
</section>
<section className="booklist">
{/* Including the Purchase component, passing the purchasedBooks props required by it */}
<Purchase books={books} purchasedBooks={this.state.purchasedBooks} />
</section>
</>
);
}
}
ReactDOM.render(<BookLibrary />, document.getElementById("container"));
Comments
Post a Comment