React Router:新组件仅在现有视图上呈现

时间:2018-09-28 17:15:13

标签: javascript reactjs react-router react-router-v4 react-router-dom

我试图在两页之间切换,但是在学习import sys from PyQt5 import QtCore, QtWidgets class MyWindow(QtWidgets.QMainWindow): def __init__(self): super().__init__() self.setWindowTitle('MyWindow') self._main = QtWidgets.QWidget() self.setCentralWidget(self._main) self.button = QtWidgets.QPushButton('Do it') self.button.clicked.connect(self.my_method) layout = QtWidgets.QGridLayout(self._main) layout.addWidget(self.button) layout.addWidget(self.button) @QtCore.pyqtSlot() def my_method(self): self.n = 5 self.loadthread = MyThread(self.n, self) self.loadthread.finished.connect(self.on_finished) self.loadthread.start() @QtCore.pyqtSlot() def on_finished(self): print('thread finished') class MyThread(QtCore.QThread): def __init__(self, n, parent=None): QtCore.QThread.__init__(self, parent) self.n = n def run(self): for i in range(self.n): print(i) print('cycle finished') if __name__ == '__main__': app = QtWidgets.QApplication.instance() if app is None: app = QtWidgets.QApplication(sys.argv) mainGui = MyWindow() mainGui.show() app.aboutToQuit.connect(app.deleteLater) sys.exit(app.exec_())

时遇到了很多问题

在我的react router内有一个底部,单击该底部可以将我导航到App.js

Cart

在购物车组件中,也有类似的按钮,可将我导航到 render() { return ( <div> <button type="button" className="btn btn-primary Bottom-right " onClick={(e) => this.handleSubmit(e)}> Confirmed Order </button> <button type="button" className="btn btn-Primary"> <Link to="/displayCart" >Show Car</Link> </button> </div> ); } } export default App; 组件。

App

我的index.js包含两个组件,应用JS是默认组件。

class Cart extends React.Component {
    constructor(props){
        super(props)

        this.state={
            cartData:null
        }
    }

    componentDidMount() {
        this.callApi()
          .then(res => this.setState({ cartData: res.express}))
          .catch(err => console.log(err));
      }

      callApi = async () => {
          const response = await fetch('/myCart');
          const body = await response.json();
          if (response.status !== 200) throw Error(body.message);

          return body;
      };

    render(){
        return(
            <div className="col">
            <div className="App">
                <header className="App-header">
                    <img src={logo} className="App-logo" alt="logo" />
                    <h1 className="App-title">Welcome to Shopping Center</h1>
                </header>
            </div>
                <div>{ReactHtmlParser(this.state.cartData)}</div>
                <button type="button Bottom-right" className="btn btn-Primary">
                    <Link to="/" >Keep Shopping</Link>
                </button>
            </div>
        )
    }
}

现在,它们确实在许多方面都是缺陷:

1:当我单击显示购物车时,而不是渲染新视图。购物车组件将呈现在视图顶部,而App仍将呈现。

2:单击“显示购物车”后,我单击“显示应用程序”以返回到我的应用程序组件,但是控制台将打印:

    ReactDOM.render(
        <BrowserRouter>
            <switch>
                <div>
                    <Route exact path="/displayCart" component={Cart}/>
                    <Route component={App} />
                </div>
            </switch>
        </BrowserRouter>,
        document.getElementById('root')
    );

3:如果从购物车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 Cart (created by Route) 返回到App组件时更改了App组件中的状态,则不会刷新该状态。例如(例如,项目中的布尔值“ purchase”。)当我从购物车的App组件取回时,状态保持为true,相反,我希望它返回到初始状态。

我遵循了本教程,但是它只是坏了。我做错了什么

1 个答案:

答案 0 :(得分:1)

因此,警告是因为setState正在调用<Cart />,即使您返回到应用程序之后,这也意味着此时已卸载购物车组件。

您应该跟踪Cart何时卸载。

您可以通过在Cart组件中创建一个变量(例如_isMounted),然后使用生命周期事件componentWillUnmount进行跟踪来做到这一点。

componentWillUnmount(){
   _isMounted =false
}

然后在使用setState之前,进行快速检查以确保_isMounted为真。

this.callApi()
          .then(res => if(isMounted){
                         this.setState({ cartData: res.express}))
                       }
          .catch(err => console.log(err));

显然,您还需要使用_isMountedComponentDidMount更改为true

这里是article on this topic


关于App的状态不是“刷新” ...这是因为当您从App>购物车> App进入时,App组件再也不会卸载并再次安装。

要解决此问题,请使用switch告诉<App />仅在URL与主页完全匹配时挂载exact path="/"组件

        <switch>
            <div>
                <Route exact path="/displayCart" component={Cart}/>
                <Route exact path="/" component={App} />
            </div>
        </switch>

现在,如果即使在API调用完成之前就已关闭(卸载),也要保持状态变化,则应在<App/>内创建一个函数,为您执行setState并将其作为道具传递给<Cart />,然后从内部传递该道具函数。

这仅在您将React Router放入

时有效

我这样做的方式是这样的:  -index.js总是加载  -然后在“我”里面重定向到显示适当的组件

这意味着始终已安装。但是,它使我可以使用App的状态作为始终存在的默认“主要”状态,因为我从未卸载过它。因此,如果我有类似...的子组件,则可以为Cart提供的功能之一。无论是否仍在安装/显示,此功能都会更改其状态。

如果您以这种方式重组应用,则可以执行以下操作:

App.js 添加一个可以更改其状态的函数。

changeState(key, value){
   this.setState({
      key : value
   }
}

现在将此功能作为道具传递

    <BrowserRouter>
        <switch>
            <div>
                <Route exact 
                       path="/displayCart" 
                       render={
                         (props) => <Cart {...props} 
                         changeStateinApp={this.changeState} /> 
                       }
                  />
                <Route component={App} />
            </div>
        </switch>
    </BrowserRouter>,

Cart.js 现在调用此函数

this.callApi()
          .then(res => 
              this.props.changeStateinApp(cartData, res.express)
          .catch(err => console.log(err));