如何在React Hooks中使用componentWillMount()?

2020/10/18 16:41 · javascript ·  · 0评论

在React的官方文档中,它提到-

如果您熟悉React类的生命周期方法,可以将useEffect Hook视为componentDidMount,componentDidUpdate和componentWillUnmount的组合。

我的问题是-我们如何componentWillMount()在钩子中使用lifecyle方法?

你不能使用任何现有的生命周期方法(componentDidMountcomponentDidUpdatecomponentWillUnmount在钩等)。它们只能在类组件中使用。而且,使用Hooks只能在功能组件中使用。下面的行来自React文档:

如果你熟悉阵营类生命周期方法,你能想到的useEffect钩。因为componentDidMountcomponentDidUpdatecomponentWillUnmount结合。

建议是,您可以从功能组件中的类组件模仿这些生命周期方法。

componentDidMount安装组件时,内部代码运行一次。useEffect钩子等效于此行为是

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

注意此处的第二个参数(空数组)。这将只运行一次。

如果没有第二个参数useEffect则会在每次渲染组件时调用钩子,这很危险。

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

componentWillUnmount用于清理(例如删除事件侦听器,取消计时器等)。假设您要在其中添加一个事件侦听器,componentDidMountcomponentWillUnmount如下所示将其删除

componentDidMount() {
  window.addEventListener('mousemove', () => {})
}

componentWillUnmount() {
  window.removeEventListener('mousemove', () => {})
}

相当于上述代码的钩子如下

useEffect(() => {
  window.addEventListener('mousemove', () => {});

  // returned function will be called on component unmount 
  return () => {
    window.removeEventListener('mousemove', () => {})
  }
}, [])

useComponentWillMount挂钩

export const useComponentWillMount = (func) => {
    const willMount = useRef(true)

    if (willMount.current) func()

    willMount.current = false
}

// or
export const useComponentWillMount = (func) => {
    useMemo(func, [])
}

在类组件中,componentWillMount被视为旧版(源1source2)。但是,这不适用于功能组件和基于挂钩的解决方案。不建议使用类组件componentWillMount,因为它可能会运行多次,并且还有一种替代方法-使用构造函数。这些注意事项与功能组件无关。

我的经验是,当定时/顺序很关键时,这样的钩子可能会节省很多。我想知道您的用例是什么-欢迎发表评论。

useComponentDidMount挂钩

或者,使用componentDidMount挂钩。

const useComponentDidMount = func => useEffect(func, []);

组件安装后(初始渲染到dom),它将仅运行一次。

演示版

const Component = (props) => {
  useComponentWillMount(() => console.log("Runs only once before component mounts"));
  useComponentDidMount(() => console.log("Runs only once after component mounts"));
  ...

  return (
    <div>{...}</div>
  );
}

完整演示

根据reactjs.org所述,将来将不再支持componentWillMount。
https://reactjs.org/docs/react-component.html#unsafe_componentwillmount

无需使用componentWillMount。

如果要在组件安装之前做一些事情,只需在构造函数()中进行即可。

如果要发出网络请求,请不要在componentWillMount中进行。这是因为这样做会导致意外的错误。

网络请求可以在componentDidMount中完成。

希望能帮助到你。


于08/03/2019更新

您要求componentWillMount的原因可能是因为您想要在渲染之前初始化状态。

只需在useState中执行即可。

const helloWorld=()=>{
    const [value,setValue]=useState(0) //initialize your state here
    return <p>{value}</p>
}
export default helloWorld;

或者,例如,如果原始代码如下所示,则可能要在componentWillMount中运行一个函数:

componentWillMount(){
  console.log('componentWillMount')
}

使用钩子,您需要做的就是删除生命周期方法:

const hookComponent=()=>{
    console.log('componentWillMount')
    return <p>you have transfered componeWillMount from class component into hook </p>
}

我只想在有关useEffect的第一个答案中添加一些内容。

useEffect(()=>{})

useEffect在每个渲染器上运行,它是componentDidUpdate,componentDidMount和ComponentWillUnmount的组合。

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

如果我们在useEffect中添加一个空数组,则它仅在安装组件时运行。这是因为useEffect将比较传递给它的数组。因此它不必是一个空数组,它可以是不变的数组。例如,它可以是[1,2,3]或['1,2']。useEffect仍然仅在安装组件时运行。

是否要运行一次还是在每次渲染后运行取决于您。只要您知道自己在做什么,就忘记添加数组,这并不危险。

我创建了一个挂钩示例。请检查一下。

https://codesandbox.io/s/kw6xj153wr


于21/08/2019更新

自从我写下以上答案以来,这一直是白人。我认为您需要注意一些事项。使用时

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

当react比较您传递给数组[]的值时,它使用Object.is()进行比较。如果将对象传递给它,例如

useEffect(()=>{},[{name:'Tom'}])

这与以下内容完全相同:

useEffect(()=>{})

每次都会重新渲染,因为当Object.is()比较对象时,它将比较其引用而不是值本身。这与为什么{} === {}返回false的原因相同,因为它们的引用不同。如果仍要比较对象本身而不是引用,则可以执行以下操作:

useEffect(()=>{},[JSON.stringify({name:'Tom'})])

useLayoutEffect[]如果功能实际上类似于componentWillMount-它可以在第一个内容到达DOM之前运行,则可以使用一组空的观察者(完成此操作–尽管实际上有两个更新,但是它们在绘制到屏幕之前是同步的。

例如:


function MyComponent({ ...andItsProps }) {
     useLayoutEffect(()=> {
          console.log('I am about to render!');
     },[]);

     return (<div>some content</div>);
}

useState对于使用初始化程序/设置程序的好处,或者useEffect尽管它可以计算渲染过程,但用户不会注意到对DOM的实际重新渲染,而是第一个值得注意的渲染之前运行,而事实并非如此。useEffect缺点当然是您的第一次渲染会稍有延迟,因为在绘画到屏幕之前必须进行检查/更新。不过,这确实取决于您的用例。

我个人认为,useMemo在某些小众情况下,您需要做一些繁重的事情就可以了-只要记住,这是例外而不是常规。

这是我使用useRef钩子在功能组件中模拟构造函数的方式

function Component(props) {
    const willMount = useRef(true);
    if (willMount.current) {
        console.log('This runs only once before rendering the component.');
        willMount.current = false;        
    }

    return (<h1>Meow world!</h1>);
}

这是生命周期示例:

function RenderLog(props) {
    console.log('Render log: ' + props.children);
    return (<>{props.children}</>);
}

function Component(props) {

    console.log('Body');
    const [count, setCount] = useState(0);
    const willMount = useRef(true);

    if (willMount.current) {
        console.log('First time load (it runs only once)');
        setCount(2);
        willMount.current = false;
    } else {
        console.log('Repeated load');
    }

    useEffect(() => {
        console.log('Component did mount (it runs only once)');
        return () => console.log('Component will unmount');
    }, []);

    useEffect(() => {
        console.log('Component did update');
    });

    useEffect(() => {
        console.log('Component will receive props');
    }, [count]);


    return (
        <>
        <h1>{count}</h1>
        <RenderLog>{count}</RenderLog>
        </>
    );
}
[Log] Body
[Log] First time load (it runs only once)
[Log] Body
[Log] Repeated load
[Log] Render log: 2
[Log] Component did mount (it runs only once)
[Log] Component did update
[Log] Component will receive props

当然,类组件没有Body步骤,由于函数和类的概念不同,无法进行1:1仿真。

您可以修改useMemo挂钩,以模仿componentWillMount生命周期事件。做就是了:

const Component = () => {
   useMemo(() => {
     // componentWillMount events
   },[]);
   useEffect(() => {
     // componentDidMount events
     return () => {
       // componentWillUnmount events
     }
   }, []);
};

您需要先保留useMemo挂钩,然后再与状态进行交互。这不是它的预期目的,但是它对所有componentWillMount问题都有效。

之所以有效,是因为useMemo不需要实际返回值,并且您不必实际将其用作任何值,但是由于它基于仅运行一次(“ []”)的依赖关系来存储值,因此它在我们组件的顶部运行当组件安装在其他组件之前时,它将运行一次。

我编写了一个自定义钩子,它将在第一次渲染之前运行一次函数。

useBeforeFirstRender.js

import { useState, useEffect } from 'react'

export default (fun) => {
  const [hasRendered, setHasRendered] = useState(false)

  useEffect(() => setHasRendered(true), [hasRendered])

  if (!hasRendered) {
    fun()
  }
}

用法:

import React, { useEffect } from 'react'
import useBeforeFirstRender from '../hooks/useBeforeFirstRender'


export default () => { 
  useBeforeFirstRender(() => {
    console.log('Do stuff here')
  })

  return (
    <div>
      My component
    </div>
  )
}

有一个很好的解决方法来实现componentDidMountcomponentWillUnmount使用useEffect

根据文档,useEffect可以返回“清理”功能。此函数将不会在第一个useEffect调用中被调用,仅在后续调用中被调用。

因此,如果我们使用useEffect完全不依赖的钩子,则仅在安装组件时才调用钩子,而在卸载该组件时才调用“ cleanup”函数。

useEffect(() => {
    console.log('componentDidMount');

    return () => {
        console.log('componentWillUnmount');
    };
}, []);

仅当卸载组件时才调用清除返回函数调用。

希望这可以帮助。

https://reactjs.org/docs/hooks-reference.html#usememo

请记住,传递给useMemo的函数在渲染期间运行。不要在渲染时执行通常不会执行的任何操作。例如,副作用属于useEffect,而不是useMemo。

本·卡尔普(Ben Carp)的回答对我来说似乎只有一个。

但是,由于我们使用的是功能方式,因此可以从闭包和HoC中受益于另一种方法:

const InjectWillmount = function(Node, willMountCallback) {
  let isCalled = true;
  return function() {
    if (isCalled) {
      willMountCallback();
      isCalled = false;
    }
    return Node;
  };
};

然后使用它:

const YourNewComponent = InjectWillmount(<YourComponent />, () => {
  console.log("your pre-mount logic here");
});

最初的问题的简短答案,如何componentWillMount与React Hooks一起使用:

componentWillMount弃用,并视为旧版反应建议

通常,我们建议使用constructor()代替初始化状态。

现在,您可以Hook FAQ中找到功能组件的类构造函数的等效项:

构造函数:功能组件不需要构造函数。您可以在useState调用中初始化状态。如果计算初始状态的成本很高,则可以将一个函数传递给useState。

因此,一个使用示例componentWillMount如下所示:

const MyComp = () => {
  const [state, setState] = useState(42) // set initial value directly in useState 
  const [state2, setState2] = useState(createInitVal) // call complex computation

  return <div>{state},{state2}</div>
};

const createInitVal = () => { /* ... complex computation or other logic */ return 42; };

只需在useEffect中添加一个空的Dependency数组,它将像一样工作componentDidMount

useEffect(() => {
  // Your code here
  console.log("componentDidMount")
}, []);

有一个简单的技巧来模拟componentDidMountcomponentWillUnmount通过使用useEffect

useEffect(() => {
  console.log("componentDidMount");

  return () => {
    console.log("componentWillUnmount");
  };
}, []);
本文地址:http://javascript.askforanswer.com/ruhezaireact-hookszhongshiyongcomponentwillmount.html
文章标签: ,   ,   ,  
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!