简体   繁体   English

无法使用 forwardRef 设置组件样式

[英]Unable to style component using forwardRef

I am fairly new to react, so still getting my head around the component's lifecycle.我对反应还很陌生,所以我仍然了解组件的生命周期。 But the problem has left me scratching my head.但这个问题让我摸不着头脑。

For instance, I do not understand why adding "setState(10);"例如,我不明白为什么要添加“setState(10);” causes style of the "Test" component to revert to it's default value yet the <div ref={ref2}>Hi</div> maintains it's style.导致“测试”组件的样式恢复为默认值,但<div ref={ref2}>Hi</div>保持其样式。 (see imagebelow) (见下图)

I am aware that "setState(10);"我知道“setState(10);” will cause a re-render but why is the style of the "Test" component being reverted?会导致重新渲染,但为什么要恢复“测试”组件的样式?

Also, please ignore the "practical use" of calling setState(10) - I am aware it is pointless as it is never used, and I am aware that using "state" as a UseEffect dependency can solve this issue.另外,请忽略调用 setState(10) 的“实际使用”——我知道它毫无意义,因为它从未被使用过,而且我知道使用“state”作为 UseEffect 依赖项可以解决这个问题。 But the main issue I have is understanding why the component's style reverts to it's default value.但我遇到的主要问题是理解为什么组件的样式会恢复为默认值。

import React, { useEffect, useState, useRef } from "react";

export default function App() {
  const [state, setState] = useState();
  let ref1 = useRef();
  let ref2 = useRef();
  useEffect(() => {
    console.log("useEffect called ", ref1.current);
    ref1.current.style.backgroundColor = "red";
    ref2.current.style.backgroundColor = "green";
    setState(10);
   // }, [state]);
  }, []);

  const Test = React.forwardRef((props, ref1) => {
    console.log("test called - rendering webpage", ref1.current);
    return (
      <div ref={ref1} {...props}>
        HI from Test{" "}
      </div>
    );
  });

  return (
    <div className="App">
      <Test ref={ref1} />
      <div ref={ref2}>Hi</div>
    </div>
  );
}

Console output控制台 output

test called - rendering webpage undefined
useEffect called <div style="background-color: red;">HI </div>
test called - rendering webpage <div style="background-color: red;">HI </div>

在此处输入图像描述

import React, { useEffect, useState, useRef } from "react";

export default function App() {
  const [state, setState] = useState();
  let ref1 = useRef();
  let ref2 = useRef();
  useEffect(() => {
    console.log("useEffect called ", ref1.current);
    ref1.current.style.backgroundColor = "red";
    ref2.current.style.backgroundColor = "green";
    setState(10);
    // }, [ref.current]);
  }, [state]);

  const Test = React.forwardRef((props, ref1) => {
    console.log("test called - rendering webpage", ref1.current);
    return (
      <div ref={ref1} {...props}>
        HI from Test{" "}
      </div>
    );
  });

  return (
    <div className="App">
      <Test ref={ref1} />
      <div ref={ref2}>Hi</div>
    </div>
  );
}

The reason this is happening is once you update the state entire component gets rerendered.发生这种情况的原因是一旦您更新 state 整个组件就会重新呈现。 Your useEffect will run only once on componentDidMount hence the new ref that you get is not updated.您的 useEffect 将仅在 componentDidMount 上运行一次,因此您获得的新参考不会更新。 To get rid of this you should use state as a dependency of the useEffect.要摆脱这种情况,您应该使用 state 作为 useEffect 的依赖项。

The reason the style is disappearing is that you've defined your Test component inside your App component.样式消失的原因是您已经App组件中定义了Test组件。 That means that every time App renders, you'll define a new component type named Test .这意味着每次App呈现时,您都将定义一个名为Test的新组件类型。 The text of that component is identical to the previous one, but it's a new type as far as react can tell, so react is forced to unmount the old one, and mount the new one.该组件的文本与前一个组件相同,但就 React 而言它是一种新类型,因此 React 被迫卸载旧组件并安装新组件。 This wipes out any changes you made to the old one.这会清除您对旧版本所做的任何更改。

So at the very least, you need to move Test outside of App .所以至少,您需要将Test移到App之外。 That way, the component is just defined once, and will not remount on every render这样,组件只定义一次,不会在每次渲染时重新挂载

export default App() {
  // ...
}

const Test = React.forwardRef((props, ref1) => {
  // ...
})

The above should fix the reset and let you experiment with refs, but i strongly recommend that you do not use refs to style your elements.上面应该修复重置并让您尝试使用 refs,但我强烈建议您不要使用 refs 来设置元素的样式。 Refs are an escape hatch that's sometimes needed, but the standard way to style a component is through the style prop. Refs 是有时需要的逃生舱口,但为组件设置样式的标准方法是通过 style 道具。 If you need to change the style, then you can have a state variable and let that control the style prop.如果你需要改变风格,那么你可以有一个 state 变量,让它控制风格道具。

If you manually use javascript to set ref1.current.style.backgroundColor , react has no way to know that you did this, and so can't take those changes into account.如果您手动使用 javascript 设置ref1.current.style.backgroundColor ,react 无法知道您这样做了,因此无法将这些更改考虑在内。 In some circumstances, react may end up overwriting your changes, or may skip making changes that it doesn't realize it needs to do.在某些情况下,React 可能最终会覆盖您的更改,或者可能会跳过它没有意识到需要做的更改。

export default function App () {
   const [colored, setColored] = useState(false);
   useEffect(() => {
     setColored(true);
   }, [])

   return (
    <div className="App">
      <Test style={colored ? { backgroundColor: "green" } : undefined} />
      <div style={colored ? { backgroundColor: "red" } : undefined}>Hi</div>
    </div>
  );
}

// Don't really need forwardRef anymore, but i left it in
const Test = React.forwardRef((props, ref) => {
  return (
    <div ref={ref} {...props}>
      HI from Test
    </div>
  );
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM