简体   繁体   中英

React - How to track useRef children change

I have a component ( Comp ) that I've added a useRef ( compRef ) to its parameters. As part of the main useEffect - I'm setting the data of this component. That data contains an array of strings, and the Comp displaying all of them as input s -

<Comp ref={compRef}>
     <input type="text"/>
</Comp>

and

data = ["HIDDEN", "data1", "data2", "data3", "data4"]

useEffect(() => { 
     compRef.current.refElement.value = data;
}, []);

so now the Comp will look like this -

<Comp>
<generatedWrap> // should be hidden
    <input value="HIDDEN" />
</generatedWrap>

<generatedWrap>
    <input value="data1" />
</generatedWrap>

<generatedWrap>
    <input value="data2" />
</generatedWrap>

<generatedWrap>
    <input value="data3" />
</generatedWrap>

<generatedWrap>
    <input value="data4" />
</generatedWrap>
</Comp>

I want to hide the first input with this hide command -

compRef.current.refElement.children[0].style.display = "none";

The problem is, that with every method (useEffect) I'm using during the mount of the screen, the children are empty. Only after the screen is ready It's working (ie triggered by a <button> )

I need a way to track the number of children of the ref before the view is mounted, and once it's greater than 1 to fire the hide command.

How can I do that?

Ok

So after a lot of testing - the only option I found is to add setTimeout(() => compRef.current.refElement.children[0].style.display = "none") after the render of the Comp .

(After the render there is still only 1 child but the fact that the setTimeout is a-synchronic make it work)

Thank you all for the help:)

I'm not sure if I've correctly understood the situation, but it seems odd to me.

Keep in mind that in React's paradigm, refs are more like an escape hatch, and should be avoided when possible.

Also, beware that for non native components, a ref can be forwarded to any element, or be handled in any way, so it is not safe to assume it will be the root element.

In any case, you may proceed as follows:

<Comp>
     <input type="text" ref={(ref) => ref && (ref.parentElement.style.display = 'none')} />
</Comp>

It is the cleanest way I can think of right now with the information I have.

Please let me know if it works for you.

Update:

The function in ref is called a Callback Ref . It will receive the corresponding ref value as the first argument (the HTML input element in this case).

The advantage is that you don't have to detect when Comp decides to populate the DOM. The callback ref will be called as soon as the real node is ready.

tldr - don't use refs to manipulate the DOM ever (unless you're an advanced react developer and know exactly what you're doing, which you aren't because these devs wouldn't be asking these questions on SO).

Don't use refs at all, you're doing React drastically wrong by manually manipulating the DOM.

Just pass the strings as props and let the component worry about displaying them:

const MyParentComponent = () => {

   return <Comp data={["HIDDEN", "data1", "data2", "data3", "data4"]}/>
}

If you want to hide a certain input in that child component, then pass another prop, for example:

const MyParentComponent = () => {

   const [indexToHide,setIndexToHide] = useState(0);

   return <Comp data={["HIDDEN", "data1", "data2", "data3", "data4"]} indexOfInputToHide={indexToHide}/>
}

and then just let Comp worry about it's props and that's it.

It's unclear what you're trying to do so the liklihood that this is the exact code you need is not great. But by continuing to try and use refs and manipulate the DOM, you are fighting against the framework and will end up having a much more difficult time in the future as you're doing react wrong, even if you do manage to come up with a working solution in this case.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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