简体   繁体   中英

Reset State on Props Change

So, I have three components(Search, Pages, HanddlesApi) plus App.js and I'm passing props around via functions to other child components with no problem.

The Search component passes it's state of userInput to HandleApi component and updates the api using componentDidUpdate. (this works great, np here).

I added the Pages component to update the api's page number so that the user can cycle through pages of content. This works, but with issues. The user can do a search and cycle though the pages, but if they enter a new query, they will land on the same page number of the new query. For example, If I searched "ducks" and clicked to the next page(2). Then did a search for "dogs" they would land on page two of "dogs"

So my question is how do I reset state for my Pages component only when a user enters a new query?

I saw that componentWillReceiveProps is being deprecated, so I can't use that. getDerivedStateFromProps seemed like it might be a good idea, but from what I read it should only be used in rare cases.

So, the two most likely options seemed to be, use componentDidUpdate in a way I don't understand or use key?

Overall I'm just confused on what to do

In my HanddlesApi Component I'm passing the follwoing into the API:

q: this.props.inputValue ? this.props.inputValue : 'news',
page: this.props.pageNum ? this.props.pageNum: 0

then..

  componentDidMount() {
        this.fetchNews()
    }

    componentDidUpdate(prevProps, prevState) {
        if (this.props.inputValue !== prevProps.inputValue || this.props.pageNum !== prevProps.pageNum) {
            this.setState({
                news: []
            }, this.fetchNews);
        }
    }

Then in my Pages Component, I have

import React, { Component } from 'react'


class Pages extends Component {
    constructor(props) {
        super(props)
        this.state = {
            nextPage: 1,
            prevPage: 0

        }

    }
    handleNextClick = () => {
        this.setState({
            nextPage: this.state.nextPage + 1,
        })
    }

    handlePrevClick = () => {
        this.setState({
            prevPage: this.state.prevPage - 1,

        })
    }

    render() {
        return (
            <div className='pageNav'>
                <button className="PrevButton" onClick={() => {
                    this.handlePrevClick()
                    this.props.onNextButtonClick(this.state.prevPage)
                }}>Previous </button>

                <button className="nextButton" onClick={() => {
                    this.handleNextClick()
                    this.props.onNextButtonClick(this.state.nextPage)
                }}>Next </button>
            </div>
        )
    }

}

export default Pages

Search Component

import React, { Component } from 'react';

class SearchBar extends Component {
    constructor(props) {
        super(props)
        this.state = {
            inputValue: ""
        }
    }
    handleChange = (e) => {
        this.setState({
            inputValue: e.target.value
        })
    }

    handleSubmit = (e) => {
        e.preventDefault()
        this.props.onSubmittedSearch(this.state.inputValue)
    }

    render() {
        //{this.props.onSubmittedSearch(this.state.inputValue)} 
        return (
            <section>
                <form onSubmit={this.handleSubmit}>
                    <label htmlFor="searching"></label>
                    <input type="text" placeholder="Search Something" value={this.state.inputValue} onChange={this.handleChange} />
                    <button type="submit">Search </button>
                </form>

            </section>
        )
    }

}

export default SearchBar

App.js

class App extends Component {
  constructor(props) {
    super(props)
    this.state = {
      inputValue: null,
      pageNum: 1

    }
  }
  // used to pass props from SearchBar to NewsList
  onSubmittedSearch = (inputValue) => {
    this.setState({
      inputValue: inputValue
    })
  }
  onNextButtonClick = (pageNum) => {
    this.setState({
      pageNum: pageNum

    })
  }



  render() {
    return (
      <main>


        <SearchBar onSubmittedSearch={this.onSubmittedSearch} />


        <NewsList inputValue={this.state.inputValue} pageNum={this.state.pageNum} />


        <Pages onNextButtonClick={this.onNextButtonClick} />
        <Footer />


      </main>
    )
  }
}

export default App;

You should let App in charge of changing and holding the current page number. So you can reset it each time your search component submit. Here is a working exemple:

 class Pages extends React.Component { render() { return (<div className='pageNav'> <button disabled={this.props.page <= 1} className="PrevButton" onClick={this.props.onPrevButtonClick}>Previous </button> <span>{this.props.page}</span> <button className="nextButton" onClick={this.props.onNextButtonClick}>Next </button> </div>) } } class SearchBar extends React.Component { constructor(props) { super(props) this.state = { inputValue: "" } } handleChange = (e) => { this.setState({inputValue: e.target.value}) } handleSubmit = (e) => { e.preventDefault() this.props.onSubmittedSearch(this.state.inputValue) } render() { //{this.props.onSubmittedSearch(this.state.inputValue)} return (<section> <form onSubmit={this.handleSubmit}> <label htmlFor="searching"></label> <input type="text" placeholder="Search Something" value={this.state.inputValue} onChange={this.handleChange}/> <button type="submit">Search </button> </form> </section>) } } class App extends React.Component { constructor(props) { super(props) this.state = { inputValue: null, pageNum: 1 } } // used to pass props from SearchBar to NewsList onSubmittedSearch = (inputValue) => { this.setState({inputValue: inputValue, pageNum: 1}) } onNextButtonClick = () => { this.setState(state => ({ pageNum: state.pageNum + 1 })) } onPrevButtonClick = (pageNum) => { this.setState(state => ({ pageNum: Math.max(state.pageNum - 1, 1) })) } render() { return (<main> <SearchBar onSubmittedSearch={this.onSubmittedSearch}/> <Pages onNextButtonClick={this.onNextButtonClick} onPrevButtonClick={this.onPrevButtonClick} page={this.state.pageNum}/> </main>) } } ReactDOM.render(<App/>, document.getElementById('root'));
 <script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script> <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script> <div id="root"></div>

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