I do not understand how to sort the books. In the parent block I created an array with all the given books, and then I don’t understand how to click on the buttons (there are 4 of them and each modifies the array in its own way: one displays it completely, the second sorts by rating, the third in popularity and the fourth displays only free books) in one child component, transfer this modified array to another child component. I am new to this business and do not understand yet how to implement it ...

  • 2
    If you add code with your implementation attempts, it will be easier to help you. - Lukas

1 answer 1

Since you did not give the code in the question, the answer will be based on recommendations with a minimum of code. So, suppose that there is a parent component, where there is an array with all the books (a banal and simple example, allBooks - all books (original array), filteredBooks - a filtered array of books, suppose that the entire list of books gets here through the download):

 const books = [ { ID: 1, Name: 'One', Author: 'Remark' }, { ID: 2, Name: 'Two', Author: 'Burunov' }, { ID: 3, Name: 'Three', Author: 'Romanov' }, ], 

Suppose that we have a certain set of books where the objects describing the books lie and this array is passed through the books parent to the parent component, or inside the componentDidMount loaded from where, then, but washed out simple, we initialize our variables in the parent's stee:

 class ParrentComponent extends React.Component { constructor(props) { super(props); this.state = { allBooks: props.books, filteredBooks: props.books, // изначально можно пустой массив `[]` } // some code here... } // some code here... } 

Suppose that we have our own filtering methods, it is possible to have a directory (in the case of Redux it would be more convenient), and these methods will also be in the parent component, for example, I will write a couple of pieces:

 showAllBooks() { const { allBooks } = this.state; this.setState({ filteredBooks: allBooks }); } filterByName(name) { const { allBooks } = this.state; const filteredBooks = allBooks.filter(book => book.Name === name) this.setState({ filteredBooks }); } filterByAuthor(author) { const { allBooks } = this.state; const filteredBooks = allBooks.filter(book => book.Author === author) this.setState({ filteredBooks }); } 

Let me draw your attention to the fact that the Array.prototype.filter() method creates a new array with all the elements that pass the test specified in the passed function, which is a safe approach and will not cause a state to mutate.

We now turn to your tea components. The first one, as I understand it, there are buttons with filters , more precisely, by pressing the buttons, one or another array will be displayed. Let us pass this component component links to our methods. The second one will contain a pop-up with a filtered list.

 <ChildWithButtons showAllBooks={this.showAllBooks} filterByName={this.filterByName} filterByAuthor={this.filterByAuthor} /> <ChildWithFilteredBooks filteredBooks={this.state.filteredBooks} /> 

Inside this component, we attach the handles of clicks to the buttons, for example, a piece of the render and processing for one button (for others in the image):

 <button onClick={this.filterByName}>Filter by name</button> 

in the same component there will be its handler for this click and a call from it to filter through the props.

 filterByName(event) { const name = 'One'; // для примера будет такое имя, его можно брать откуда угодно this.props.filterByName(name); // вызовем метод фильтрации из пропсы } 

After clicking on the button, the method from the props will be called, the array will be filtered out and the second component will be updated, which will use the filtered array, as its filteredBooks will be updated. So, through props from one parent component, you can communicate between its two child components. Please note that we do not change the original allBooks array, but use it as a source for filtering. Do not forget about the banding inside the constructor, if this is suddenly needed, but it is needed.

It will also be useful to read:

  • I pass to the child component <General filteredBooks = {this.state.filteredBooks} /> In the child I write <div className = "general"> {this.props.filteredBooks.map ((index, key) => but I get an error {TypeError: Cannot read property 'map' of undefined at General.render} - Yuri Korolik
  • I created an array of const books = [{ID: 1, Name: 'Jewels of Nizam', Author: 'by Geeta Devi',}, {ID: 2, Name: 'Cakes & Bakes', Author: 'by Sanjeev Kapoor' }, {ID: 3, Name: 'Jamie's Kitchen', Author: 'by Jamie Oliver'}, before class App extends React.Component {constructor (props) {super (props); this.state = {AllBooks: props.books, filteredBooks: props.books,}}; then there are filters, everything as you described after - Yuri Korolik
  • <Nav action showAllBooks = {this.showAllBooks} filterByName = {this.filterByName} filterByAuthor = {this.filterByAuthor} /> in the General component I write the General extends React.Component {render () {return (<div className = "general "> {this.props.filteredBooks.s.map ((index, key) => <div> </ div>)} </ div>)}} export default General; - Yuri Korolik
  • so probably codepen.io/and-1991/pen/dwMXpg would be better - Yuri Korolik
  • @Yuriy Korolik you don’t send your books through props , write this: this.state = { AllBooks: books, filteredBooks: books, } . You forgot to make bind methods in the constructor (like this: this.filterByName = this.filterByName.bind(this); ), also you do not follow the case of letters in variables - this is important ( AllBooks and allBooks are different variables). Quite a lot of comments on the code, be careful. - Denis Bubnov