我能使用ref.current.setState(...)吗?

3
我有一个需要从父组件Parent调用Child.method的情况,虽然这不是最佳实践,但我想试一试。我决定在Parent组件中使用ref.current.setState()。以下是示例代码:https://codesandbox.io/s/8lmvq3yq68
refsetStatereact-router-dom同时使用时,会出现一些意外行为。当我同时使用Redirectref时,Child.componentDidUpdate将不会被调用。我想知道这是否是React中有效的代码?因为我找不到任何文档表明它无效。或者这是react-router-dom的一个bug吗?请帮忙解答。

你不需要一个引用来做这个,只需要任何旧对象就可以了。但是如果你要使用一个引用,我相信如果你想传递方法,那么在子组件上使用forwardRef是一种方法。 - Andria
在你的例子中,你可以将 name 作为一个属性传递给 Superhero,从而避免整个引用复杂性。有没有什么原因使这不可行? - Joel Cornett
1个回答

0

我添加了一些额外的组件生命周期日志以进行澄清。

所以当你选择'Link'到'/'时,会有两个并行的调用。

  1. 导航到'/'路径
  2. onClick事件

其中一个将首先导航到相关路径,而另一个将触发ref的函数。你会看到"Calling the state change"的日志。

当你路由到'/'路径时,SuperHero组件被卸载!你会看到"Unmounting - Superhero"的日志。因此状态改变丢失,componentDidUpdate不会被触发。尽管如此,正如你所见,重定向确实发生了,并且组件再次被挂载。现在它没有状态改变的意义,但是"Mounting - Superhero"将被记录。

我还单独添加了一个按钮。由于没有卸载,这个按钮按预期工作!

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);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接