componentDidMount 等效于 React 函数/Hooks 组件吗?

IT技术 javascript reactjs react-hooks
2021-03-09 22:10:21

有没有办法componentDidMount通过钩子在 React 功能组件中进行模拟

6个回答

对于钩子的稳定版本(React 版本 16.8.0+)

为了 componentDidMount

useEffect(() => {
  // Your code here
}, []);

为了 componentDidUpdate

useEffect(() => {
  // Your code here
}, [yourDependency]);

为了 componentWillUnmount

useEffect(() => {
  // componentWillUnmount
  return () => {
     // Your code here
  }
}, [yourDependency]);

所以在这种情况下,你需要将你的依赖传递到这个数组中。假设你有这样的状态

const [count, setCount] = useState(0);

每当计数增加时,您都想重新渲染您的功能组件。那么你useEffect应该看起来像这样

useEffect(() => {
  // <div>{count}</div>
}, [count]);

这样,每当您的计数更新时,您的组件都会重新渲染。希望这会有所帮助。

这个答案是错误的,它暗示它相当于 componentDidMount(问题是要求一个等价物),它只显示了在某些情况下有效的解决方法。正确答案应说明没有等效项,并为所有用例显示推荐的解决方法。
2021-04-17 22:10:21
我一直在尝试使用空依赖数组来模拟 componentDidMount。问题是它通常会导致警告:“React Hook useEffect 缺少依赖项:<some prop>。要么包含它,要么删除依赖项数组 react-hooks/exhaustive-deps”。应用任一建议的“修复”使其不再表现为 componentDidMount。难道我做错了什么?
2021-04-18 22:10:21
谢谢你,因为我不知道useState. 对于阅读本文的任何人,请记住,保留第二个参数undefined将导致您的效果在每次渲染时触发(如果我没记错的话)。
2021-04-23 22:10:21
这是互联网上最简洁的 useEffect() 文档。
2021-04-23 22:10:21
即使它存在,我也不知道。你可以检查这个线程 tho github.com/facebook/react/issues/3279
2021-05-12 22:10:21

componentDidMount在react-hooks中没有确切的等价物


根据我的经验,react hooks 在开发时需要不同的思维方式,一般来说,你不应该将它与componentDidMount.

随着中说,有办法,你可以用钩子产生类似的效果componentDidMount

解决方案1:

useEffect(() => {
  console.log("I have been mounted")
}, [])

解决方案2:

const num = 5

useEffect(() => {
  console.log("I will only run if my deps change: ", num)
}, [num])

方案三(带函数):

useEffect(() => {
  const someFunc = () => {
    console.log("Function being run after/on mount")
  }
  someFunc()
}, [])

解决方案4(useCallback):

const msg = "some message"

const myFunc = useCallback(() => {
  console.log(msg)
}, [msg])

useEffect(() => {
  myFunc()
}, [myFunc])

解决方案 5(发挥创意):

export default function useDidMountHook(callback) {
  const didMount = useRef(null)

  useEffect(() => {
    if (callback && !didMount.current) {
      didMount.current = true
      callback()
    }
  })
}

值得注意的是,只有在其他解决方案都不适合您的用例时,才应该真正使用解决方案 5如果您确实决定需要解决方案 5,那么我建议您使用这个预先制作的钩子 use-did-mount

来源(更多细节):在react-hooks中使用 componentDidMount

没有componentDidMount功能组件,但是 React Hooks 提供了一种可以通过使用useEffect钩子来模拟行为的方法

将一个空数组作为第二个参数传递useEffect()给仅在 mount 上运行回调。

请阅读 上的文档useEffect

function ComponentDidMount() {
  const [count, setCount] = React.useState(0);
  React.useEffect(() => {
    console.log('componentDidMount');
  }, []);

  return (
    <div>
      <p>componentDidMount: {count} times</p>
      <button
        onClick={() => {
          setCount(count + 1);
        }}
      >
        Click Me
      </button>
    </div>
  );
}

ReactDOM.render(
  <div>
    <ComponentDidMount />
  </div>,
  document.querySelector("#app")
);
<script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script>

<div id="app"></div>

尽管接受的答案有效,但不建议这样做。当您有多个状态并且您将它与 useEffect 一起使用时,它会警告您将其添加到依赖项数组或根本不使用它。

它有时会导致问题,这可能会给您带来不可预测的输出。所以我建议你花点力气把你的函数重写为类。几乎没有变化,您可以将一些组件作为类,将一些组件作为函数。您没有义务只使用一种约定。

以这个为例

function App() {
  const [appointments, setAppointments] = useState([]);
  const [aptId, setAptId] = useState(1);

  useEffect(() => {
    fetch('./data.json')
      .then(response => response.json())
      .then(result => {
        const apts = result.map(item => {
          item.aptId = aptId;
          console.log(aptId);
          setAptId(aptId + 1);
          return item;
        })
        setAppointments(apts);
      });
  }, []);

  return(...);
}

class App extends Component {
  constructor() {
    super();
    this.state = {
      appointments: [],
      aptId: 1,
    }
  }

  componentDidMount() {
    fetch('./data.json')
      .then(response => response.json())
      .then(result => {
        const apts = result.map(item => {
          item.aptId = this.state.aptId;
          this.setState({aptId: this.state.aptId + 1});
          console.log(this.state.aptId);
          return item;
        });
        this.setState({appointments: apts});
      });
  }

  render(...);
}

这只是举例所以我们不要谈论代码的最佳实践或潜在问题。这两者具有相同的逻辑,但后者只能按预期工作。您可能会在此时运行 useEffect 时获得 componentDidMount 功能,但是随着您的应用程序的增长,您可能会遇到一些问题。因此,与其在那个阶段重写,不如在早期进行。

此外,OOP 也没有那么糟糕,如果面向过程编程就足够了,我们就永远不会有面向对象编程了。有时很痛苦,但更好(技术上。撇开个人问题)。

我还没有看到无法通过重构代码解决的 useEffect 'gotcha' - 这个例子包括在内。使用回调版本setState或将有问题的函数完全移出渲染周期通常可以解决问题 - 如果没有,您的状态可能太复杂了,您需要实现自己的减速器。Hooks 不是强制性的,但它显然是 React 的未来。我推荐阅读这篇关于 useEffect 的优秀文章——当我开始遇到这些问题时,它确实帮助我解决了这个问题。
2021-04-24 22:10:21
我这样做了。我遇到了使用钩子的问题。将其转换为类后问题就消失了。
2021-05-01 22:10:21

useEffect()钩子允许我们实现 componentDidMount 的功能,componentDidUpdate componentWillUnMount 功能。

useEffect() 的不同语法允许实现上述每个方法。

i) componentDidMount

useEffect(() => {
  //code here
}, []);

ii) componentDidUpdate

useEffect(() => {
  //code here
}, [x,y,z]);

//where x,y,z are state variables on whose update, this method should get triggered

iii) componentDidUnmount

useEffect(() => {
  //code here
  return function() {
    //code to be run during unmount phase
  }
}, []);

您可以查看官方 react 站点以获取更多信息。Hooks 上的官方 React 页面