I have a PaymentWidgetFooter component with three buttons.
const PaymentWidgetFooter = React.forwardRef((props, ref) => {
return(
<div ref={ref}>
<button className={`...`} onClick={() => props.setActiveView(1)} />
<button className={`...`} onClick={() => props.setActiveView(2)} />
<button className={`...`} onClick={() => props.setActiveView(3)} />
</div>
);
}
Its props consist of a setActiveView() function that the component calls and supplies with a number between 1-3 (inclusive) as a parameter.
<NewPaymentWidgetFooter ref={footerRef} setActiveView={() => setActiveView()} />
Once this happens, a useEffect hook notices the change in the state variable of the parent component and triggers a updateSubviewStyles() function which updates a dictionary that is supplied to other views to set their absolute position.
useEffect(() => {
updateSubviewStyles()
}, [activeView])
function updateSubviewStyles() {
setSubviewStyle(prevState => ({
...prevState,
1: {
...prevState[1],
left: (1 - activeView) * viewOneRef.current.clientWidth
},
2: {
...prevState[2],
left: (2 - activeView) * viewOneRef.current.clientWidth
},
3: {
...prevState[3],
left: (3 - activeView) * viewOneRef.current.clientWidth
}
}))
}
activeView is the state variable that the setActiveView() function changes and viewOneRef is a reference to a div that's always rendered but may be hidden due to overflow-hidden (and has absolute position).
The challenge I'm dealing with is that clicking on any of the three buttons causes the subviewStyle dictionary to contain left: NaN values for all three children.
Confusingly, if I hardcode a value that gets called when NewPaymentWidgetFooter calls the setActiveView like below:
<NewPaymentWidgetFooter ref={footerRef} setActiveView={() => setActiveView(2)} />
then everything works fine and subviewStyle contains appropriate values for the left keys (e.g., left: 424).
Why does the dynamic option not work when hardcoding a parameter to pass back does?
CodePudding user response:
The setActiveView prop value you pass to NewPaymentWidgetFooter is () => setActiveView(), which will always call setActiveView without any parameters. If you pass it a function that calls setActiveView with its parameter, like this
<NewPaymentWidgetFooter ref={footerRef} setActiveView={(n) => setActiveView(n)}/>
it should use the value you pass to the callback.
