我可以使用ref.current.setState(...)

时间:2019-03-23 05:22:37

标签: javascript reactjs react-router

我有一种情况想要从Child.method调用Parent,尽管这不是最佳实践,但我只想尝试一下。我决定在ref.current.setState()组件中使用Parent

这是示例代码。 https://codesandbox.io/s/8lmvq3yq68

refsetStatereact-router-dom一起使用时发生了一些意外的行为。当我同时使用Redirectref时,将不会调用Child.componentDidUpdate。我想知道它在React中是否有效?由于找不到任何文档,因此显示该文档无效。还是react-router-dom的错误?

1 个答案:

答案 0 :(得分:0)

我登录了一些其他组件生命周期日志以进行澄清。 因此,发生的事情是当您选择“链接”到“ /”时,将触发两个并行调用。

  1. 导航到“ /”路线
  2. onClick事件

因此,一个人将首先导航至相关路线,而另一个人将触发裁判的功能。您将看到“调用状态更改”日志。

  

当您路由到“ /”路径时,发生的是 SuperHero   组件已卸载!,您将看到“正在卸载-超级英雄”   日志。因此,状态更改会丢失,并且不会触发componentDidUpdate。但是,如您所见,重定向确实发生了   然后再次安装该组件。现在它没有状态了   更改,但将记录“安装-超级英雄”。

我还包括一个单独的按钮。由于没有卸载,因此可以按预期工作!

https://codesandbox.io/s/81v0mz0548

import React from "react";
import ReactDOM from "react-dom";
import {
  BrowserRouter as Router,
  Link,
  Redirect,
  Route
} from "react-router-dom";

import "./styles.css";

class App extends React.Component {
  constructor(props) {
    super(props);
    this.superheroElement = React.createRef();
  }
  handleClick = () => {
    this.superheroElement.current.changeName();
  };
  render() {
    return (
      <Router>
        <Link to={"/"} onClick={this.handleClick}>
          haha
        </Link>
        <Route path="/" exact={true} render={() => <Redirect to="/post" />} />
        <Route
          path="/post"
          render={props => <Superhero ref={this.superheroElement} {...props} />}
        />
        <br/>
        <button  onClick={this.handleClick}>
          haha
        </button>
      </Router>
    );
  }
}

class Superhero extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      name: "Batman"
    };
    this.changeName = this.changeName.bind(this);
  }

  changeName() {
    console.log("Calling the state change");
    this.setState({
      name: "Bruce Wayne"
    });
  }

  componentDidUpdate() {
    // Not called because component is unmounted
    console.log("Updating - Superhero");
  }

  componentDidMount() {
    console.log("Mounting - Superhero");
  }

  componentWillUnmount() {
    console.log("Unmounting - Superhero");
  }

  render() {
    return <div>{this.state.name}</div>;
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);