代码之家  ›  专栏  ›  技术社区  ›  Thuan Nguyen

如何在react中的unmount组件中设置state

  •  0
  • Thuan Nguyen  · 技术社区  · 7 年前

    componentDidMount

    我的问题是警告反应通知:

    Warning: Can't call setState (or forceUpdate) on an unmounted 
    component. This is a no-op, but it indicates a memory leak in your 
    application. To fix, cancel all subscriptions and asynchronous tasks in the 
    componentWillUnmount method.
    in DiscoverPage (created by Route)
    

    DiscoverPage 组件:

    import React, { Component } from 'react';
    import { Switch, Route, Redirect } from 'react-router-dom';
    import TvShows from './TvShows';
    import Movies from './Movies';
    import MovieDetail from "../MoviePage/MovieDetail";
    import TvDetail from "../TvShowPage/TvDetail";
    
    class DiscoverPage extends Component {
    
    constructor(props) {
        super(props);
        this.state = {
            data: {}
        }
    }
    
    getDataItem = (data) => {
        this.setState({ data: data });
    };
    
    render() {
        return (
            <Switch>
                <Route exact path="/discover/movie" render={props => <Movies data={this.getDataItem} {...props} />} />
                <Route path="/discover/tv" render={props => <TvShows data={this.getDataItem} {...props} />} />
                <Route path="/movie/:movie" render={props => <MovieDetail data={this.state.data} {...props} />} />
                <Route path="/tv/:tv" render={props => <TvDetail data={this.state.data} {...props} />} />
                <Redirect to="/discover/movie" />
            </Switch>
        );
    }
    }
    
    export default DiscoverPage;
    

    Movies

    import React, { Component } from 'react';
    import requestApi from '../api';
    import MovieList from "../MoviePage/MovieList";
    
    class Movies extends Component {
    
    constructor(props) {
        super(props);
        this.state = {
            data: {
                page: 1,
                results: []
            }
        }
    }
    
    componentDidMount() {
        requestApi.fetchData('discover', 'movie').then(response => {
            this.setState({ data: response.data, isLoading: false });
        });
    }
    
    getMoviebyId = (id) => {
        requestApi.fetchDataById('movie', id).then(response => {
            this.props.data(response.data);
        });
    };
    
    nextPage = (e) => {
        const page = this.state.data.page + 1;
        requestApi.fetchDataPaginate('discover', 'movie', page).then(response => {
            this.setState({data: response.data});
        });
    };
    prevPaginate = (e) => {
        const page = this.state.data.page - 1;
        requestApi.fetchDataPaginate('discover', 'movie', page).then(response => {
            this.setState({ data: response.data });
        });
    };
    
    render() {
        return (
            <div className="container">
                <div className="ss_media">
                    <h2 className="title">Discover New Movies & TV Shows</h2>
                    <MovieList
                        movie={this.getMoviebyId}
                        routeProps={this.props}
                        prevPaginate={this.prevPaginate}
                        nextPaginate={this.nextPage}
                        moviesList={this.state.data} />
                </div>
            </div>
        );
    }
    }
    
    export default Movies;
    

    5 回复  |  直到 7 年前
        1
  •  1
  •   cosh    7 年前

    setState 在未安装的组件上,即当前未呈现的组件上。最有可能的是,您的其他组件之一( Movies TvShows data 支柱。当呈现其中一个组件时, DiscoveryPage getDataItem 通过 道具将导致 未呈现时要调用的方法。为了解决这个问题(假设您要做的是将数据从一个组件传递到另一个组件),我建议您可以使用 localStorage

    设置状态 component... componentWillUnmount

    编辑: Movie 本地存储 getMovieById 方法,而不是:

    getMoviebyId = (id) => {
        requestApi.fetchDataById('movie', id).then(response => {
            //this next sentence will call DiscoveryPage's setState
            //DiscoveryPage is not mounted, so a warning will be raised
            this.props.data(response.data);
        });
    };
    

    getMoviebyId = (id) => {
        requestApi.fetchDataById('movie', id).then(response => {
            //any component can access this store
            localStorage.setItem("data", response.data);
        });
    };
    

    localStorage.getItem("data");
    

    您的代码有点混乱。我很难理解你在哪里使用 数据

    ,管理它是一个很好的做法,我的意思是打电话来 localStorage.removeItem("data") 组件将卸载

        2
  •  2
  •   Anu Zedorg    7 年前

    react-router render methods

    <Route path="/user/:username" component={User}/>
    
        3
  •  1
  •   jadlmir    7 年前


    import React, { Component } from 'react';
    import { Switch, Route, Redirect } from 'react-router-dom';
    import TvShows from './TvShows';
    import Movies from './Movies';
    import MovieDetail from '../MoviePage/MovieDetail';
    import TvDetail from '../TvShowPage/TvDetail';
    
    class DiscoverPage extends Component {
        constructor(props) {
            super(props);
            this.state = {
                data: {}
            };
        }
        getALLDATA() {
            //update your state after your request
            request().then(res => {
                this.setState({
                    data: res.data
                });
            });
        }
        componentDidMount() {
            this.getALLDATA();
        }
        getDataItem = () => {
            return this.state.data;
        };
    
        render() {
            return (
                <Switch>
                    <Route exact path="/discover/movie" render={props => <Movies data={this.getDataItem} {...props} />} />
                    <Route path="/discover/tv" render={props => <TvShows data={this.getDataItem} {...props} />} />
                    <Route path="/movie/:movie" render={props => <MovieDetail data={this.state.data} {...props} />} />
                    <Route path="/tv/:tv" render={props => <TvDetail data={this.state.data} {...props} />} />
                    <Redirect to="/discover/movie" />
                </Switch>
            );
        }
    }
    
    export default DiscoverPage;
    
        4
  •  0
  •   Damian Peralta    7 年前

    react-router-dom

    import { Switch, Route, Redirect, BrowserRouter } from 'react-router-dom'; // Add BrowserRouter
    
    class DiscoverPage extends Component {
    
    ...
    render() {
        return (
        <BrowserRouter> // Add this 
            <Switch>
                <Route exact path="/discover/movie" render={props => <Movies data={this.getDataItem} {...props} />} />
                <Route path="/discover/tv" render={props => <TvShows data={this.getDataItem} {...props} />} />
                <Route path="/movie/:movie" render={props => <MovieDetail data={this.state.data} {...props} />} />
                <Route path="/tv/:tv" render={props => <TvDetail data={this.state.data} {...props} />} />
                <Redirect to="/discover/movie" />
            </Switch>
        </BrowserRouter>
        );
    }
    }
    
        5
  •  0
  •   sametcodes Tetramputechture    7 年前

    比如:

    componentDidMount(){
        var {state, setState} = this.props;
        setState({doNotRender: true});
    }
    

    componentDidUpdate(){
        var {state, setState} = this.props;
        if(!state.doNotRender){ //any_condition ur choice
           setState({doNotRender: true});
        }
    }