Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
322 views
in Technique[技术] by (71.8m points)

reactjs - useEffect is not triggered by a change in ref.current from a child component

I have created a popup that the user can use to add stuff to the application, every field is a separate component, because I need to reuse them in several places in different configruations.

I have tried to create an innerRef that when changed (i.e. new value is typed), the useEffect of the component should be triggered to show or hide the Done button if all values are valid.

I know that all values are valid or not from the valid prop that I assign to .current

export default function AddStock() {
  const selectTypeOfQuantityRef = useRef({});
  const [allValid, setAllValid] = useState(false);

  useEffect(() => {
    const allValues = [selectTypeOfQuantityRef.current.valid];

    allValues.every((value) => value) ? setAllValid(true) : setAllValid(false);
    console.log(allValues.every((value) => value)); // does not get triggered
  }, [selectTypeOfQuantityRef.current]);

return (
    <>
      <AddPopup>
        <SelectTypeOfQuantity innerRef={selectTypeOfQuantityRef} />
        {allValid && <DoneButton/>}
        <CancelButton/>
      </AddPopup>
    </>
  );
}

And this is the select itself (custom of course), that sets innerRef, whenever its state changes. Everything here works, the state of this small component itself is managed correctly, but it just does not get triggered the state update of the parent component

export default function SelectTypeOfQuantity({ defaultValue = null, innerRef }) {
  const [selectTypeOfQuantity, setSelectTypeOfQuantity] = useState(defaultValue);
  const [valid, setValid] = useState(false);
  const [errMessage, setErrMessage] = useState("Избери стойност!");

  useEffect(() => {
    innerRef.current.value = selectTypeOfQuantity;
    handleValidation(selectTypeOfQuantity);
  }, [selectTypeOfQuantity]);

  const handleValidation = (value) => {
    const result = validateAutocomplete(value);
    if (result.valid) {
      setValid(true);
      setErrMessage(null);
      innerRef.current.valid = result.valid;
    } else {
      setValid(false);
      setErrMessage(result.errMessage);
    }
  };

  const selectTypeOfQuantityOnChange = (e, val) => {
    setSelectTypeOfQuantity(val ? val.value : null);
  };

  return (
    <Select onChange={selectTypeOfQuantityOnChange}/>
  );
}
question from:https://stackoverflow.com/questions/65950842/useeffect-is-not-triggered-by-a-change-in-ref-current-from-a-child-component

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

useRef does not trigger rerenders, thus useEffect will not be called

Use useRef when you need information that is available regardless of component lifecycle and whose changes should NOT trigger rerenders. Use useState for information whose changes should trigger rerenders.

Solution

As React's Philosophy states, all the data must reside within React, that's why even input components are supplied with a value and onChange event. React can't track data changes that happens outside it. As I understand from your question, the changes are happending within the React App, So instead of tracking the data through the innerRef, track them within React using React's own methods.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...