Open alucardu opened 3 years ago
@alucardu Thanks for opening an issue! The warning seems to have something to do with Code Sandbox and the hot reload code they’re using. I’m not too sure if this is a problem if the page is working as expected.
The warning:
Warning: Cannot update a component (`Movies`) while rendering a different component (`Login`). To locate the bad setState() call inside `Login`, follow the stack trace as described in https://reactjs.org/link/setstate-in-render
Login
div
App
ApolloProvider
Hey @brainkim I have this same issue on my local app, except then it appears when the app loads (not on a reload). I'm also not sure if there's a problem since everything is working as expected, but I'm still getting the warning.
@alucardu I’ll look into it! Sorry about the trouble! If you have a reproduction of it happening on load and not reload that would be super helpful!
https://github.com/facebook/react/issues/22252#event-5261949382 perhaps this is something that could help?
@alucardu Looking at this again, it looks like there is a reactiveVar update (moviesVar([{name: 'Movie name'}])
) directly in the render function in Login.tsx
. This is akin to calling setState()
directly in the render function. Perhaps, if you move it to a useEffect()
call, the warnings will go away?
I'm having a similar issue, though all of my calls to set my reactive variables are either in a useEffect()
or inside a function, not directly in the render. For example:
export const AddressModal = ({
addressModalOpen,
authenticatedUserAddress,
isAuthenticated,
onClose,
isTablet
}: ModalProps) => {
const [localAddress, setLocalAddress] = useState('');
const [deliveryInstructions, setDeliveryInstructions] = useState('');
const [addressLabel, setAddressLabel] = useState('');
const [isDefault, setIsDefault] = useState(false);
const [mapVisible, setMapVisible] = useState(false);
const [editCustomerAddress] = useMutation(CUSTOMER_ADD_ADDRESS, {
refetchQueries: [{ query: CUSTOMER_ADDRESS_DATA }, { query: CUSTOMER_DATA }]
});
...
const handleSave = async () => {
const googleAddress: GoogleAddress = await getCoordinatesFromAddress(localAddress);
setLocalState('deliveryAddress', googleAddress);
const addressExists = await isExistingAddress(googleAddress, authenticatedUserAddress);
if (!addressExists) {
const address = {
customerNotes: deliveryInstructions,
isDefault: isDefault,
streetAddress: googleAddress.streetAddress,
streetAddress2: googleAddress.streetAddress2,
city: googleAddress.city,
state: googleAddress.state,
zip: googleAddress.zip,
label: addressLabel
};
try {
editCustomerAddress({
variables: {
address: {
...address
}
}
});
} catch (error) {
logger.error(error);
}
// }
}
setMapVisible(false);
onClose();
};
...
The reactive var is being set by the setLocalState
call on line 2 of the handleSave()
function. setLocalState
is a wrapper that sets the reactive var and persists the value in local storage for offline use and use by micro front-ends. Here is the wrapper:
export const setLocalState = <T extends keyof typeof VARIABLES>(
key: T,
value: ReturnType<typeof VARIABLES[T]['var']>
) => {
const reactiveVar: ReactiveVar<any> = VARIABLES[key].var;
localStorage.setItem(key, getCleanValueForStorage(value));
reactiveVar(value);
};
Where VARIABLES is an object of reactiveVariables, like this
export const VARIABLES = {
deliveryAddress: {
var: deliveryAddressReactiveVar
},
};
And deliveryAddressReactiveVar is defined as
import { makeVar } from '@apollo/client';
import { Address } from '@/shared/src/types/address';
export const deliveryAddressReactiveVar = makeVar<Address>({});
Intended outcome:
Trying to set a value in a reactive variable in one component (
Login
) and read the value in a different component (Movies
)The values are set/passed/read correctly, but a warning shows up.
Actual outcome:
How to reproduce the issue: Visit > https://codesandbox.io/s/sleepy-fire-im8ug?file=/src/App.js:216-221 On initial load the app works fine.
Versions