防止组件被 React-router 卸载

IT技术 reactjs react-router
2021-05-06 12:46:13

当涉及到React-Router组件时,我很笨拙但是,当我浏览链接时,我无法解释为什么我的组件会被卸载?以及如何预防?

在我的示例中,我有一个包含计时器和重新渲染内容的组件

我有一个错误:

在此处输入图片说明

这是 ReactJS 代码:

/*global define, Backbone, React, $, Request, Router, Route, Link */

var App = React.createClass({
    render: function () {
        return (
            <div>
                <h1>App</h1>
                <ul>
                    <li><Link to="/about">About</Link></li>
                    <li><Link to="/timer">Timer</Link></li>
                </ul>
                {this.props.children}
            </div>
        )
    }
});

var About = React.createClass({
    render: function () {
        return <h3>Here is about page</h3>
    }
});

var Timer = React.createClass({
    getInitialState: function() {
        return {counter: 0};
    },
    render: function () {
        return (
            <div>
                <h2>Time is running over...</h2>
                <b>{this.props.interval}</b>
                <p>{this.state.counter}</p>
            </div>
        )
    },
    componentDidMount: function () {
        this.loadCommentsFromServer();
        setInterval(this.loadCommentsFromServer, 1000);
    },
    loadCommentsFromServer: function () {
        this.setState({counter: this.state.counter + 1});
    }
});

React.render((
    <Router location="history">
        <Route path="/" component={App}>
            <Route path="about" component={About} />
            <Route path="timer" component={Timer} />
        </Route>
    </Router>
), document.body);
3个回答

如果您想在不卸载的情况下再次显示组件,您可以始终显示它并在路由离开时隐藏它。为了达到这个地方你可以在目标路线之外,例如你想防止ProjectsList脱机:

   <Route path="/" component={App}>
        <IndexRoute component={ProjectsList} />
        .....

1.ProjectsList放入App并创建这样的代理组件component={ProjectsList}

  const LayoutToogler = () => (<div></div>);

看起来会这样:

    <Route path="/(mobile.html)" component={App}>
        <IndexRoute component={LayoutToogler} showProjects={true}/>
  1. 在顶级 App 组件中,只需检查此属性 ( showProjects) 即可决定是否显示项目:

           <ProjectsList
             style={{display:this.props.children.props.route.showProjects?'block':'none'}}
                    />
    

不要忘记处理组件中的style属性ProjectList

在您的情况下 react-router 按预期工作,如果您希望计时器在整个应用程序中可见,那么您需要处理的是组件而不是视图

/*global define, Backbone, React, $, Request, Router, Route, Link */

var App = React.createClass({
    render: function () {
        return (
            <div>
                <h1>App</h1>
                // this will not unmount when routes are changed
                <Timer /> 
                <ul>
                    <li><Link to="/about">About</Link></li>
                </ul>
                // this will unmount/mount when routes are changed
                {this.props.children}
            </div>
        )
    }
});

var About = React.createClass({
    render: function () {
        return <h3>Here is about page</h3>
    }
});

var Timer = React.createClass({
    getInitialState: function() {
        return {counter: 0};
    },
    render: function () {
        return (
            <div>
                <h2>Time is running over...</h2>
                <b>{this.props.interval}</b>
                <p>{this.state.counter}</p>
            </div>
        )
    },
    componentDidMount: function () {
        this.loadCommentsFromServer();
        setInterval(this.loadCommentsFromServer, 1000);
    },
    loadCommentsFromServer: function () {
        this.setState({counter: this.state.counter + 1});
    }
});

React.render((
    <Router location="history">
        <Route path="/" component={App}>
            <Route path="about" component={About} />
        </Route>
    </Router>
), document.body);

为了避免在路由器再次挂载您的组件时获取/构建大/慢数据块,您可以这样做:1)实现一个全局缓存对象(只需在纯javascript中从您的应用程序的根目录导出一个空对象level) 2) 在您的组件中,执行以下操作:

import {cache} from '.....App';
const myComponent = props => {
if (!cache.myBigList) {
  cache.myBigList = [];
}
const [list, setList] = useState(cache.myBigList);
cache.myBigList = list;
...

这样,第一次挂载组件时,它会在 [] 处启动缓存。然后每次更改列表时再次执行该函数并将列表保存在缓存中。再次挂载组件时,赋予 useState 的初始状态是上次挂载周期中最后保存的状态。