StrictMode中不推荐使用findDOMNode,而是如何使用引用

时间:2020-08-31 20:36:10

标签: javascript reactjs routes react-router

大家好,我只是想在路由器转换期间使用Refs定位组件中元素的方法。当前,来自React Transition Group的onEnter,onExit和addEndListener事件已使您可以访问要设置动画的DOM节点。这段时间还不错,但是现在您可能已经知道您得到了错误。

index.js:1警告:StrictMode中不建议使用findDOMNode。 findDOMNode传递了StrictMode内部的Transition实例。而是直接将引用添加到要引用的元素。了解有关安全使用裁判的更多信息[1]

这是我的App.js代码

    import React from 'react';
    import { BrowserRouter as Router, Route } from 'react-router-dom';
    import { CSSTransition } from 'react-transition-group';
    import { gsap } from 'gsap';
  

    import Header from './tools/header';
    import About from './pages/about';
    import Home from './pages/home';

    const routes = [
        { path: '/', name: 'Home', Component: Home },
        { path: '/about', name: 'About', Component: About },

    ]

    function Routeapp() {

        const nodeRef = React.useRef(null);

        const onEnter = (node) => {
            console.log(node)

            gsap.from(
                [node.children[0].firstElementChild, node.children[0].lastElementChild],
                {
                    duration: 0.6,
                    y: 30,
                    delay: 0.6,
                    ease: 'power3.inOut',
                    opacity: 0,
                    stagger: {
                        amount: 0.3,
                    },
                }
            );

        };

        const onExit = node => {
            gsap.to(
                [node.children[0].firstElementChild, node.children[0].lastElementChild],
                {
                    duration: 0.6,
                    y: -30,
                    ease: 'power3.inOut',
                    opacity: 0,
                    stagger: {
                        amount: 0.15,
                    },
                }
            );
        };

      return (
        <Router>
          <Header />
          <div className="container">
              {routes.map(({ path, Component }) => (
                  <Route key={path} exact path={path}>
                      {({ match }) => (
                          <CSSTransition
                              in={match != null}
                              key={path}
                              timeout={1200}
                              classNames="page"
                              onEnter={onEnter}
                              onExit={onExit}
                              unmountOnExit={true}

                          >
                              <div className="page" ref={nodeRef} >
                                  <Component />
                              </div>
                          </CSSTransition>
                      )}
                  </Route>
              ))}
          </div>
        </Router>
      );
    }
    export default Routeapp;

Home.js

import React from 'react';
import Title from '../tools/title';

const Home = () => {
  return (

          <div className="inner">
              <Title lineContent="this is the" lineContent2="Home page" />
              <div className={'infoBox'}>
                  <p className="info">hello mel and welcome</p>
              </div>
          </div>
  );
};

export default Home;

about.js

import React from 'react';
import Title from '../tools/title';

const About = () => {
  return (

        <div className="inner">
          <Title lineContent={'this is the'} lineContent2={'About page'} />
          <div className={'infoBox'}>
            <p className="info pink">
              Lorem Ipsum is simply dummy text of the printing and typesetting
              industry. Lorem Ipsum has been the industry's standard dummy text ever
              since the 1500s, when an unknown printer took a galley of type and
              scrambled it to make a type specimen book. It has survived not only
              five centuries, but also the leap into electronic typesetting,
              remaining essentially unchanged. It was popularised in the 1960s with
              the release of Letraset sheets containing Lorem Ipsum passages, and
              more recently with desktop publishing software like Aldus PageMaker
              including versions of Lorem Ipsum.
            </p>
          </div>
        </div>
  );
};

export default About;

我的问题是我试图找到一种方法来“引用”我的“家庭”和“关于”组件,这样我不仅可以为其设置动画,还可以在“ onExit”和“ onEnter”道具中添加不同的补间。可能。

我尝试通过在app.js中尝试直接“引用”组件:

return (
    <Router>
      <Header />
      <div className="container">
          {routes.map(({ path, Component }) => (
              <Route key={path} exact path={path}>
                  {({ match }) => (
                      <CSSTransition
                          in={match != null}
                          key={path}
                          nodeRef={nodeRef}
                          timeout={1200}
                          classNames="page"
                          onEnter={onEnter}
                          onExit={onExit}
                          unmountOnExit={true}

                      >
                          <div className="page" ref={nodeRef} >
                              <Component />
                          </div>
                      </CSSTransition>
                  )}
              </Route>
          ))}
      </div>
    </Router>
  );

如预期的那样,这导致我的应用程序停止工作,因为'nodeRef'返回false,并且当使用nodeRef prop时,因为用户已经可以直接访问该节点,所以该节点没有传递给回调函数(例如onEnter)。

所以我现在只需要一种新的方式来做以后的参考,任何见解或想法都会受到欢迎。

谢谢

3 个答案:

答案 0 :(得分:1)

所以我只想向@Slbox大声疾呼,他启发了我更深入地研究问题。

免责声明

我不是javascript方面的专家或专业程序员,我绝不建议这是实现此目的的唯一方法,我的演示文稿应该以抽象的方式进行。我的想法只是说明该解决方案所基于的理论前提,而该解决方案的实现将取决于您自己的体系结构。

查找节点“ findDOMNode”

因此,在React Strict模式下,当您要引用页面上的元素时,将优先使用'FindDomNode,并且倾向于使用'Ref'友好方法。像很多人一样,我收到的讨厌错误消息弹出来,告诉您“ findDOMNode在严格模式下已贬值”。

用例(为什么遇到问题)

在React Router中,我使用了来自'react-transition-group'的'CSSTransition'和基于Javascript的动画平台'GSAP'的组合,创建了一个简单的页面过渡。我遇到的问题是我使用DOM节点方法将元素引用为反应中的首选方法。

1。重组应用程序组件

language_of_your_choice.json

2。主页/关于组件

// So the App now has the routes contained inside each component in order for it
// to work and add additional functions and flexibility.

import React from 'react';
import { BrowserRouter as Router } from 'react-router-dom';

import './route.scss';

import Header from './tools/header';
import About from './pages/about';
import Home from './pages/home';

function Routeapp() {


  return (
    <Router>
      <Header />
      <div className="container">
          <Home /> <!-- routes and funcs -->
          <About /> <!-- routes and funcs -->
      </div>
    </Router>
  );
}

export default Routeapp;

GSAP and React-Router EXAMPLE

结论

这是我达到这种效果的方法,但是如果有更好或替代的方法,请加讨论并分享。

答案 1 :(得分:1)

@W9914420 的回答引导我找到了解决此问题的方法。

我只想从所有代码行中添加,最相关的是:

  • 声明一个引用的实例:
    const nodeRef = useRef(null)
  • 将该引用作为属性注入到组件中:
    <CSSTransition ``
        in={match != null}
        // time should not really be longer than the time it takes the animation
        // to leave the scene.
        timeout={1200}
        classNames={'page'}
        nodeRef={nodeRef}
        onEnter={onEnter}
        onExit={onExit}
        unmountOnExit
        >

感谢@W9914420 的提示!

答案 2 :(得分:1)

快速解决方案是:

./src/index.js 文件并将其更改为:

   ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);

为此:

ReactDOM.render(
    <App />
  document.getElementById('root')
);