简体   繁体   中英

ReactJS component doesn't re-render

I have a following example simple page:

App.js :

export default class App extends React.Component {
    render() {
        return <Router>
            <Switch>
                <Route exact path='/' component={ArticlesPage}/>
                <Route path='/search' component={SearchPage}/>
            </Switch>
        </Router>
    };
};

ArticlesPage.js :

export default class ArticlesPage extends React.Component {
    constructor(props) {
        super(props);
    }

    render() {
        return <Grid>
            <Row>
                <Col lg={12}>
                    <SearchBox/>
                </Col>
            </Row>
            <Row>
                <Col lg={12}>
                    articles
                </Col>
            </Row>
        </Grid>;
    }
};

SearchPage.js :

export default class SearchPage extends React.Component {
    constructor(props) {
        super(props);
        const {q} = queryString.parse(location.search);
        this.state = {
            query: q
        };
    }

    render() {
        return <Grid>
            <Row>
                <Col lg={12}>
                    <SearchBox/>
                </Col>
            </Row>
            <Row>
                <Col lg={12}>
                    search {this.state.query}
                </Col>
            </Row>
        </Grid>;
    }
};

SearchBox.js :

export default class SearchBox extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            q: ''
        };
    }

    onFormSubmit = (e) => {
        e.preventDefault();
        const {router} = this.context;
        router.history.push('/search?q=' + this.state.q);
    };

    handleChange = (e) => {
        this.setState({q: e.target.value});
    };

    render() {
        return <form onSubmit={this.onFormSubmit}>
            <Col lg={10} lgOffset={1}>
                <FormGroup>
                    <input type="text" name="q" id="q" ref={i => this.searchInput = i} onChange={this.handleChange} />
                </FormGroup>
            </Col>
        </form>;
    }
};

And now, when I'm on the index page and type something in the input next send form, React render SearchPage.js and return correctly text search *and what I typed* , try again type something else in the input and send form, and React still show my previous text (not rerender).

What can be wrong with this simple page?

You have two different state variables, query on <SearchPage /> and q on <SearchBox /> . What you are changing is q , but the variable you are rendering as text is query .

You need to lift state up and pass query as prop to <SearchPage /> .

Here's why the text on SearchPage doesn't update: the constructor runs once and updates the variable in state, but when the app re-renders, React, wanting to be efficient, sees that it would re-render a new SearchPage in the same spot as the previous one, so instead of replacing it, it keeps the state of the old one. Because of this, SearchPage 's state still keeps the old q variable.

Here's how you can fix it: make your SearchPage accept the search query as a prop, and render that.

class SearchPage extends React.Component {
  render() {
    return (
      <Grid>
        <Row>
          <Col lg={12}>
            <SearchBox />
          </Col>
        </Row>
        <Row>
          <Col lg={12}>search {this.props.query}</Col>
        </Row>
      </Grid>
    )
  }
}

In the parent, where the route for it is being rendered, use a render function, take the props of it, parse the actual query from props.location.search , and pass it directly to SearchPage .

<Route
  path="/search"
  render={props => <SearchPage query={getSearchQuery(props.location.search)} />}
/>

// utility function to keep things clean
function getSearchQuery(locationSearch) {
  return queryString.parse(locationSearch.slice(1)).q
}

Here's a working demo.

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