By iPhoneJavaDev


2020-05-22 23:07:06 8 Comments

I have the following components:

const ParentComponent: React.FC = () => {
    // Somewhere in the code, I set this to some value
    const [newType, setNewType] = useState<any>(undefined);

    // Somewhere in the code, I set this to true
    const [enableAddEdge, setEnableAddEdge] = useState(false);

    const addEdge = (data: any) => {
        console.log("newType", newType); // This is undefined
    }

    return (
    ...
        <VisNetwork 
            newType={newType}
            onAddEdge={addEdge}
            enableAddEdge={enableAddEdge}
        />
    ...
    )
}
export default ParentComponent;

interface Props {
    newType: any;
    onAddEdge: (data: any) => void;
    enableAddEdge: boolean;
}
const VisNetwork: React.FC<Props> = (props: Props) => {
    const options: any = {
        // Some vis-network specific option configuration
        manipulation: {
            addEdge: (data: any, callback: any) => props.onAddEdge(data);
        }
    }
    ...
    // Some code to create the network and pass in the options
    const network = new vis.Network(container, networkData, options);

    useEffect(() => {
        if (props.enableAddEdge) {
            // This confirms that indeed newType has value
            console.log("newType from addEdge", props.newType);

            // Call reference to network (I name it currentNetwork)
            // This will enable the adding of edge in the network.  
            // When the user is done adding the edge,
            // the `addEdge` method in the `options.manipulation` will be called.
            currentNetwork.addEdgeMode();
        }
    }, [props.enableAddEdge])

    useEffect(() => {
        if (props.newType) {
            // This is just to confirm that indeed I am setting the newType value
            console.log("newType from visNetwork", props.newType); // This has value
        }
    }, [props.newType]);
}
export default VisNetwork;

When the addEdge method is called, the newType state becomes undefined. I know about the bind but I don't know if it's possible to use it and how to use it in a functional component. Please advise on how to obtain the newType value.

Also, from VisNetwork, I want to access networkData state from inside options.manipulation.addEdge. I know it's not possible but any workaround? I also need to access the networkData at this point.

1 comments

@Zachary Haber 2020-05-22 23:32:38

You need to useRef in this scenario. It appears const network = new vis.Network(container, networkData, options); uses the options from the first render only. Or something similar is going on.

It's likely to do with there being a closure around newType in the addEdge function. So it has stale values: https://reactjs.org/docs/hooks-faq.html#why-am-i-seeing-stale-props-or-state-inside-my-function

In order to combat this, you need to useRef to store the latest value of newType. The reference is mutable, so it can always store the current value of newType without re-rendering.

// Somewhere in the code, I set this to some value
const [newType, setNewType] = useState<any>(undefined);

const newTypeRef = useRef(newType);
useEffect(() => {
  // Ensure the ref is always at the latest value
  newTypeRef.current = newType;
}, [newType])

const addEdge = (data: any) => {
    console.log("newType", newTypeRef.current); // This is undefined
}

Related Questions

Sponsored Content

96 Answered Questions

[SOLVED] How can I remove a specific item from an array?

  • 2011-04-23 22:17:18
  • Walker
  • 6835583 View
  • 8412 Score
  • 96 Answer
  • Tags:   javascript arrays

37 Answered Questions

[SOLVED] What is the difference between React Native and React?

42 Answered Questions

[SOLVED] How do I remove a property from a JavaScript object?

64 Answered Questions

[SOLVED] Loop inside React JSX

  • 2014-04-05 05:29:28
  • Ben Roberts
  • 842085 View
  • 1301 Score
  • 64 Answer
  • Tags:   javascript reactjs

33 Answered Questions

[SOLVED] Programmatically navigate using react router

  • 2015-06-26 17:38:51
  • George Mauer
  • 757413 View
  • 1470 Score
  • 33 Answer
  • Tags:   reactjs react-router

39 Answered Questions

[SOLVED] How do I return the response from an asynchronous call?

26 Answered Questions

[SOLVED] What do these three dots in React do?

  • 2015-06-25 11:21:52
  • Thomas Johansen
  • 277849 View
  • 922 Score
  • 26 Answer
  • Tags:   javascript reactjs

11 Answered Questions

[SOLVED] How to access the correct `this` inside a callback?

34 Answered Questions

[SOLVED] What is the difference between state and props in React?

  • 2015-01-16 19:28:27
  • skaterdav85
  • 200684 View
  • 567 Score
  • 34 Answer
  • Tags:   javascript reactjs

Sponsored Content