Issue with state setter not working inside useEffect async API call in a custom API component
25 replies
Last updated: Jun 21, 2022
O
Im creating a custom api calling input however the useState setter is not working inside useEffect async api call. Sorry for the long winded code message. Here’s my code if someone can assist:
const AsyncSelect = React.forwardRef((props, ref) => { const [sessions, setSessions] = useState([]) const { type, // Schema information value, // Current field value readOnly, // Boolean if field is not editable placeholder, markers, // Markers including validation rules presence, // Presence information for collaborative avatars compareValue, // Value to check for "edited" functionality onFocus, // Method to handle focus state onBlur, // Method to handle blur state onChange // Method to handle patch events } = props // Creates a change handler for patching data const handleChange = React.useCallback( // useCallback will help with performance (event) => { const inputValue = event.currentTarget.value // get current value // if the value exists, set the data, if not, unset the data onChange(PatchEvent.from(inputValue ? set(inputValue) : unset())) }, [onChange] ) const inputId = useId() useEffect(() => { const getSessions = async () => { const data = await fetch("<https://api.call>") const json = await data.json() const tSessions = await setSessions(json.collection) //NOT WORKING!!! } getSessions() .catch(console.error); }, []) return ( <FormField description={type.description} // Creates description from schema title={type.title} // Creates label from schema title __unstable_markers={markers} // Handles all markers including validation __unstable_presence={presence} // Handles presence avatars compareValue={compareValue} // Handles "edited" status inputId={inputId} // Allows the label to connect to the input field > <Card padding={0}> <Stack> <Select id={inputId} // A unique ID for this input fontSize={2} padding={[3, 3, 4]} space={[3, 3, 4]} value={value} // Current field value readOnly={readOnly} // If "readOnly" is defined make this field read only onFocus={onFocus} // Handles focus events onBlur={onBlur} // Handles blur events ref={ref} onChange={handleChange} // A function to call when the input value changes > <option value={''}>---</option> {sessions.map((s) => ({ s.name}) </Select> </Stack> </Card> </FormField> ) }) export default AsyncSelect
Jun 21, 2022, 3:37 PM
K
Hey Removed Name , can you please use a single message to describe your problem? This way we can use a single thread to discuss and the channel remains free in the meantime. 🙂
Jun 21, 2022, 3:48 PM
O
sure, sorry about that
Jun 21, 2022, 3:50 PM
O
can I use something like the
react-querypackage inside a sanity app?
Jun 21, 2022, 3:51 PM
O
been trying to get it to work for hours, this is painful
Jun 21, 2022, 3:51 PM
K
State setters are not aynchronous, so you can’t
await. They also don’t return anything, so you shouldn’t have to store it in a constant.
Jun 21, 2022, 4:07 PM
K
You can log your data after the
.json()call to check what you receive.
Jun 21, 2022, 4:08 PM
O
i can see what I receive, im getting the data, its just not being set to the sessions variable
Jun 21, 2022, 4:09 PM
O
any ideas?
Jun 21, 2022, 4:27 PM
K
Can you show a console log?
Jun 21, 2022, 4:31 PM
O
also getting this long erre
Check the render method of `ForwardRef`. See <https://fb.me/react-warning-keys> for more information. in option (created by ForwardRef) in ForwardRef (created by FormBuilderInputInner) in ChangeIndicatorProvider (created by FormBuilderInputInner) in div (created by FormBuilderInputInner) in FormBuilderInputInner (created by FormBuilderInput) in FormBuilderInput (created by ForwardRef(ObjectInputField)) in ConditionalHiddenField (created by ForwardRef(ObjectInputField)) in ForwardRef(ObjectInputField) (created by ForwardRef(ObjectInput)) in ConditionalReadOnlyContextProvider (created by ConditionalReadOnlyField) in ConditionalReadOnlyField (created by ForwardRef(ObjectInput)) in div (created by styled.div) in styled.div (created by ForwardRef(Box)) in ForwardRef(Box) (created by Styled(Component)) in Styled(Component) (created by ForwardRef(Grid)) in ForwardRef(Grid) (created by ForwardRef(ObjectInput)) in ForwardRef(ObjectInput) in ForwardRef(ObjectInput) (created by FormBuilderInputInner) in ChangeIndicatorProvider (created by FormBuilderInputInner) in div (created by FormBuilderInputInner) in FormBuilderInputInner (created by FormBuilderInput) in FormBuilderInput (created by SanityFormBuilder) in ReviewChangesContextProvider (created by SanityFormBuilder) in FormBuilderContext (created by SanityFormBuilderContext) in SanityFormBuilderContext (created by SanityFormBuilder) in SanityFormBuilder (created by FormView) in form (created by styled.div) in styled.div (created by ForwardRef(Box)) in ForwardRef(Box) (created by FormView) in div (created by ForwardRef(RegionsWithIntersections)) in div (created by styled.div) in styled.div (created by ForwardRef(RegionsWithIntersections)) in ForwardRef(RegionsWithIntersections) (created by StickyOverlay) in StickyOverlay (created by OverlayEnabled) in Tracker (created by OverlayEnabled) in OverlayEnabled (created by FormView) in div (created by styled.div) in styled.div (created by ForwardRef(Box)) in ForwardRef(Box) (created by Styled(Component)) in Styled(Component) (created by ForwardRef(Container)) in ForwardRef(Container) (created by FormView) in FormView (created by DocumentPanel) in div (created by ForwardRef(ScrollContainer)) in ForwardRef(ScrollContainer) (created by Styled(Component)) in Styled(Component) (created by DocumentPanel) in BoundaryElementProvider (created by DocumentPanel) in PortalProvider (created by DocumentPanel) in div (created by styled.div) in styled.div (created by ForwardRef(Box)) in ForwardRef(Box) (created by Styled(Component)) in Styled(Component) (created by ForwardRef(Card)) in Fe (created by ThemeProvider) in ThemeProvider (created by ThemeColorProvider) in ThemeColorProvider (created by ForwardRef(Card)) in ForwardRef(Card) (created by PaneContent__root) in PaneContent__root (created by ForwardRef(PaneContent)) in ForwardRef(PaneContent) (created by DocumentPanel) in div (created by styled.div) in styled.div (created by ForwardRef(Box)) in ForwardRef(Box) (created by Styled(Component)) in Styled(Component) (created by ForwardRef(Flex)) in ForwardRef(Flex) (created by DocumentPanel) in DocumentPanel (created by InnerDocumentPane) in div (created by ForwardRef(ScrollContainer)) in ForwardRef(ScrollContainer) (created by EnabledChangeConnectorRoot) in Tracker (created by EnabledChangeConnectorRoot) in EnabledChangeConnectorRoot (created by Styled(EnabledChangeConnectorRoot)) in Styled(EnabledChangeConnectorRoot) (created by InnerDocumentPane) in div (created by styled.div) in styled.div (created by ForwardRef(Box)) in ForwardRef(Box) (created by Styled(Component)) in Styled(Component) (created by ForwardRef(Flex)) in ForwardRef(Flex) (created by InnerDocumentPane) in DialogProvider (created by InnerDocumentPane) in div (created by styled.div) in styled.div (created by ForwardRef(Box)) in ForwardRef(Box) (created by Styled(Component)) in Styled(Component) (created by ForwardRef(Flex)) in ForwardRef(Flex) (created by ForwardRef(Pane)) in BoundaryElementProvider (created by ForwardRef(Pane)) in div (created by styled.div) in styled.div (created by ForwardRef(Box)) in ForwardRef(Box) (created by Styled(Component)) in Styled(Component) (created by ForwardRef(Card)) in Fe (created by ThemeProvider) in ThemeProvider (created by ThemeColorProvider) in ThemeColorProvider (created by ForwardRef(Card)) in ForwardRef(Card) (created by Styled(Component)) in Styled(Component) (created by ForwardRef(Pane)) in LayerProvider (created by LegacyLayerProvider) in LegacyLayerProvider (created by ForwardRef(Pane)) in ForwardRef(Pane) (created by KeyboardShortcutResponder) in KeyboardShortcutResponder (created by GetHookCollectionState) in GetHookCollectionState (created by RenderActionCollectionState) in RenderActionCollectionState in Unknown (created by InnerDocumentPane) in InnerDocumentPane (created by DocumentPane) in ReferenceInputOptionsProvider (created by DocumentPane) in Unknown (created by DocumentPane) in DocumentPane (created by DeskToolPane) in PaneRouterProvider (created by DeskToolPane) in DeskToolPane in DeskToolPane in div (created by styled.div) in styled.div (created by ForwardRef(Box)) in ForwardRef(Box) (created by Styled(Component)) in Styled(Component) (created by ForwardRef(Card)) in Fe (created by ThemeProvider) in ThemeProvider (created by ThemeColorProvider) in ThemeColorProvider (created by ForwardRef(Card)) in ForwardRef(Card) (created by Styled(Component)) in Styled(Component) (created by PaneLayout) in PaneLayout (created by Styled(PaneLayout)) in Styled(PaneLayout) in PortalProvider in DeskToolProvider in Unknown (created by DeskToolRoot) in ErrorBoundary (created by DeskToolRoot) in DeskToolRoot (created by RenderTool) in ErrorBoundary (created by RenderTool) in RenderTool (created by SchemaErrorReporter) in RouteScope (created by SchemaErrorReporter) in div (created by styled.div) in styled.div (created by ForwardRef(Box)) in ForwardRef(Box) (created by Styled(Component)) in Styled(Component) (created by ForwardRef(Flex)) in ForwardRef(Flex) (created by Styled(Component)) in Styled(Component) (created by SchemaErrorReporter) in div (created by styled.div) in styled.div (created by ForwardRef(Box)) in ForwardRef(Box) (created by Styled(Component)) in Styled(Component) (created by ForwardRef(Flex)) in ForwardRef(Flex) (created by Styled(Component)) in Styled(Component) (created by SchemaErrorReporter) in div (created by styled.div) in styled.div (created by ForwardRef(Box)) in ForwardRef(Box) (created by Styled(Component)) in Styled(Component) (created by ForwardRef(Flex)) in ForwardRef(Flex) (created by Styled(Component)) in Styled(Component) (created by SchemaErrorReporter) in SchemaErrorReporter (created by DefaultLayout) in DefaultLayout (created by DefaultLayoutRoot) in RouterProvider (created by DefaultLayoutRoot) in LoginWrapper (created by NormalizedLoginWrapper) in NormalizedLoginWrapper (created by DefaultLayoutRoot) in DefaultLayoutRoot (created by AppProvider) in div (created by styled.div) in styled.div (created by ForwardRef(Box)) in ForwardRef(Box) (created by Styled(Component)) in Styled(Component) (created by ForwardRef(Card)) in Fe (created by ThemeProvider) in ThemeProvider (created by ThemeColorProvider) in ThemeColorProvider (created by ForwardRef(Card)) in ForwardRef(Card) (created by Styled(Component)) in Styled(Component) (created by AppProvider) in SnackbarProvider (created by AppProvider) in ToastProvider (created by AppProvider) in LayerProvider (created by AppProvider) in PortalProvider (created by AppProvider) in UserColorManagerProvider (created by AppProvider) in AppProvider (created by SanityRoot) in Fe (created by ThemeProvider) in ThemeProvider (created by SanityRoot) in ZIndexProvider (created by SanityRoot) in SanityRoot in AppContainer
Jun 21, 2022, 4:53 PM
O
but im guessing it’s giving this warning because im mapping over the array and it’s empty
Jun 21, 2022, 4:55 PM
O
maybe use class component instead of hooks?
Jun 21, 2022, 4:57 PM
O
can i maybe fetch products ahead of time and save the array as json somewhere in the app?
Jun 21, 2022, 5:18 PM
S
Hi Removed Name , perhaps this guide by
user M
could help? 🙂 https://www.sanity.io/guides/asynchronous-list-options Jun 21, 2022, 6:10 PM
O
hey thanks Removed Name , I’ve been looking at that guide but for some reason, my state setter isn’t updating the same way as in the guide
Jun 21, 2022, 6:12 PM
O
trying to implement a class based component now, let’s see
Jun 21, 2022, 6:12 PM
S
The problem is that you’re not setting the state correctly, you can’t set state with await as Kitty explained. You need to do something like the following instead:
Hopefully your state should be populated with the colors from your api call, which you should see in your drop-down input
useEffect(() => { const getSessions = async () => { const data = await fetch('<https://api.call>') .then(res => res.json()) .then(json => json.data.map(({ color }) => ({ title: color, value: color.toLowerCase().split(' ').join('-') }))) setSessions(data) } getSessions() }, [])
Jun 21, 2022, 6:23 PM
O
yea i fixed that and it still doesn’t set the state
Jun 21, 2022, 6:25 PM
K
but im guessing it’s giving this warning because im mapping over the array and it’s empty
No, it's totally fine to do that. Nothing would warn for that reason.
Jun 21, 2022, 6:27 PM
O
ok it’s working, im getting the data in the select as options and I can select/inspect it
Jun 21, 2022, 6:47 PM
O
however, im still getting this error:
Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()? Check the render method of `FormBuilderInputInner`. in CalendlyAsyncSelect (created by FormBuilderInputInner) in ChangeIndicatorProvider (created by FormBuilderInputInner) in div (created by FormBuilderInputInner) in FormBuilderInputInner (created by FormBuilderInput) in FormBuilderInput (created by ForwardRef(ObjectInputField)) in ConditionalHiddenField (created by ForwardRef(ObjectInputField)) in ForwardRef(ObjectInputField) (created by ForwardRef(ObjectInput)) in ConditionalReadOnlyContextProvider (created by ConditionalReadOnlyField) in ConditionalReadOnlyField (created by ForwardRef(ObjectInput)) in div (created by styled.div) in styled.div (created by ForwardRef(Box)) in ForwardRef(Box) (created by Styled(Component)) in Styled(Component) (created by ForwardRef(Grid)) in ForwardRef(Grid) (created by ForwardRef(ObjectInput)) in ForwardRef(ObjectInput) in ForwardRef(ObjectInput) (created by FormBuilderInputInner) in ChangeIndicatorProvider (created by FormBuilderInputInner) in div (created by FormBuilderInputInner) in FormBuilderInputInner (created by FormBuilderInput) in FormBuilderInput (created by SanityFormBuilder) in ReviewChangesContextProvider (created by SanityFormBuilder) in FormBuilderContext (created by SanityFormBuilderContext) in SanityFormBuilderContext (created by SanityFormBuilder) in SanityFormBuilder (created by FormView) in form (created by styled.div) in styled.div (created by ForwardRef(Box)) in ForwardRef(Box) (created by FormView) in div (created by ForwardRef(RegionsWithIntersections)) in div (created by styled.div) in styled.div (created by ForwardRef(RegionsWithIntersections)) in ForwardRef(RegionsWithIntersections) (created by StickyOverlay) in StickyOverlay (created by OverlayEnabled) in Tracker (created by OverlayEnabled) in OverlayEnabled (created by FormView) in div (created by styled.div) in styled.div (created by ForwardRef(Box)) in ForwardRef(Box) (created by Styled(Component)) in Styled(Component) (created by ForwardRef(Container)) in ForwardRef(Container) (created by FormView) in FormView (created by DocumentPanel) in div (created by ForwardRef(ScrollContainer)) in ForwardRef(ScrollContainer) (created by Styled(Component)) in Styled(Component) (created by DocumentPanel) in BoundaryElementProvider (created by DocumentPanel) in PortalProvider (created by DocumentPanel) in div (created by styled.div) in styled.div (created by ForwardRef(Box)) in ForwardRef(Box) (created by Styled(Component)) in Styled(Component) (created by ForwardRef(Card)) in Fe (created by ThemeProvider) in ThemeProvider (created by ThemeColorProvider) in ThemeColorProvider (created by ForwardRef(Card)) in ForwardRef(Card) (created by PaneContent__root) in PaneContent__root (created by ForwardRef(PaneContent)) in ForwardRef(PaneContent) (created by DocumentPanel) in div (created by styled.div) in styled.div (created by ForwardRef(Box)) in ForwardRef(Box) (created by Styled(Component)) in Styled(Component) (created by ForwardRef(Flex)) in ForwardRef(Flex) (created by DocumentPanel) in DocumentPanel (created by InnerDocumentPane) in div (created by ForwardRef(ScrollContainer)) in ForwardRef(ScrollContainer) (created by EnabledChangeConnectorRoot) in Tracker (created by EnabledChangeConnectorRoot) in EnabledChangeConnectorRoot (created by Styled(EnabledChangeConnectorRoot)) in Styled(EnabledChangeConnectorRoot) (created by InnerDocumentPane) in div (created by styled.div) in styled.div (created by ForwardRef(Box)) in ForwardRef(Box) (created by Styled(Component)) in Styled(Component) (created by ForwardRef(Flex)) in ForwardRef(Flex) (created by InnerDocumentPane) in DialogProvider (created by InnerDocumentPane) in div (created by styled.div) in styled.div (created by ForwardRef(Box)) in ForwardRef(Box) (created by Styled(Component)) in Styled(Component) (created by ForwardRef(Flex)) in ForwardRef(Flex) (created by ForwardRef(Pane)) in BoundaryElementProvider (created by ForwardRef(Pane)) in div (created by styled.div) in styled.div (created by ForwardRef(Box)) in ForwardRef(Box) (created by Styled(Component)) in Styled(Component) (created by ForwardRef(Card)) in Fe (created by ThemeProvider) in ThemeProvider (created by ThemeColorProvider) in ThemeColorProvider (created by ForwardRef(Card)) in ForwardRef(Card) (created by Styled(Component)) in Styled(Component) (created by ForwardRef(Pane)) in LayerProvider (created by LegacyLayerProvider) in LegacyLayerProvider (created by ForwardRef(Pane)) in ForwardRef(Pane) (created by KeyboardShortcutResponder) in KeyboardShortcutResponder (created by GetHookCollectionState) in GetHookCollectionState (created by RenderActionCollectionState) in RenderActionCollectionState in Unknown (created by InnerDocumentPane) in InnerDocumentPane (created by DocumentPane) in ReferenceInputOptionsProvider (created by DocumentPane) in Unknown (created by DocumentPane) in DocumentPane (created by DeskToolPane) in PaneRouterProvider (created by DeskToolPane) in DeskToolPane in DeskToolPane in div (created by styled.div) in styled.div (created by ForwardRef(Box)) in ForwardRef(Box) (created by Styled(Component)) in Styled(Component) (created by ForwardRef(Card)) in Fe (created by ThemeProvider) in ThemeProvider (created by ThemeColorProvider) in ThemeColorProvider (created by ForwardRef(Card)) in ForwardRef(Card) (created by Styled(Component)) in Styled(Component) (created by PaneLayout) in PaneLayout (created by Styled(PaneLayout)) in Styled(PaneLayout) in PortalProvider in DeskToolProvider in Unknown (created by DeskToolRoot) in ErrorBoundary (created by DeskToolRoot) in DeskToolRoot (created by RenderTool) in ErrorBoundary (created by RenderTool) in RenderTool (created by SchemaErrorReporter) in RouteScope (created by SchemaErrorReporter) in div (created by styled.div) in styled.div (created by ForwardRef(Box)) in ForwardRef(Box) (created by Styled(Component)) in Styled(Component) (created by ForwardRef(Flex)) in ForwardRef(Flex) (created by Styled(Component)) in Styled(Component) (created by SchemaErrorReporter) in div (created by styled.div) in styled.div (created by ForwardRef(Box)) in ForwardRef(Box) (created by Styled(Component)) in Styled(Component) (created by ForwardRef(Flex)) in ForwardRef(Flex) (created by Styled(Component)) in Styled(Component) (created by SchemaErrorReporter) in div (created by styled.div) in styled.div (created by ForwardRef(Box)) in ForwardRef(Box) (created by Styled(Component)) in Styled(Component) (created by ForwardRef(Flex)) in ForwardRef(Flex) (created by Styled(Component)) in Styled(Component) (created by SchemaErrorReporter) in SchemaErrorReporter (created by DefaultLayout) in DefaultLayout (created by DefaultLayoutRoot) in RouterProvider (created by DefaultLayoutRoot) in LoginWrapper (created by NormalizedLoginWrapper) in NormalizedLoginWrapper (created by DefaultLayoutRoot) in DefaultLayoutRoot (created by AppProvider) in div (created by styled.div) in styled.div (created by ForwardRef(Box)) in ForwardRef(Box) (created by Styled(Component)) in Styled(Component) (created by ForwardRef(Card)) in Fe (created by ThemeProvider) in ThemeProvider (created by ThemeColorProvider) in ThemeColorProvider (created by ForwardRef(Card)) in ForwardRef(Card) (created by Styled(Component)) in Styled(Component) (created by AppProvider) in SnackbarProvider (created by AppProvider) in ToastProvider (created by AppProvider) in LayerProvider (created by AppProvider) in PortalProvider (created by AppProvider) in UserColorManagerProvider (created by AppProvider) in AppProvider (created by SanityRoot) in Fe (created by ThemeProvider) in ThemeProvider (created by SanityRoot) in ZIndexProvider (created by SanityRoot) in SanityRoot in AppContainer
Jun 21, 2022, 6:47 PM
O
IT WORKS!
Jun 21, 2022, 6:56 PM
O
wrap the component in React.useRef and pass ref to the select and error is gone
Jun 21, 2022, 6:56 PM
O
here is the code:
import React from 'react' import fetch from 'node-fetch' import PatchEvent, {set, unset} from 'part:@sanity/form-builder/patch-event' import FormField from 'part:@sanity/components/formfields/default' import DefaultSelect from 'part:@sanity/components/selects/default' const CalendlyAsyncSelect = React.forwardRef((props, ref) => { const unsetItem = {title: '', value: 'unset'} const getSessions = async () => { const data = await fetch(`<https://api.calendly.com/event_types?user=https://api.calendly.com/users/3a1c8403-dc60-438f-a50c-045471f1c4b9>`, { "method": "GET", "headers": { "Content-Type": "application/json", "Authorization": "Bearer eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL2F1dGguY2FsZW5kbHkuY29tIiwiaWF0IjoxNjUyMDg2NDk0LCJqdGkiOiIyNjI5ZTg0OS01OGRmLTQyN2MtYjE1Zi05ZTY3MjJlYzkxNTgiLCJ1c2VyX3V1aWQiOiIzYTFjODQwMy1kYzYwLTQzOGYtYTUwYy0wNDU0NzFmMWM0YjkifQ.CSPb-TOXj5FuYSTOiN8Ga9o7EktCMOXd9fJuDXJVYLE" } }) .then(res => res.json()) .then(tsessions => tsessions.collection.map(({name, uri}) => { return { title: name, value: uri } })).then(data => setExperiments([unsetItem, ...data])) } const setValue = (item) => { const {value} = item const {onChange} = props onChange(PatchEvent.from(value === 'unset' ? unset() : set(value))) } React.useEffect(() => { getSessions() }, []) const [experiments, setExperiments] = React.useState([]) const {type, value} = props const {title, description} = type const currentValue = experiments.find(({value: optionVal}) => optionVal === value) return ( <FormField label={title} description={description}> <DefaultSelect ref={ref} value={currentValue} placeholder={'Select value'} items={experiments} onChange={setValue} /> </FormField> ) }) export default CalendlyAsyncSelect
Jun 21, 2022, 6:56 PM
O
Jun 21, 2022, 6:57 PM
Sanity– build remarkable experiences at scale
Sanity is a modern headless CMS that treats content as data to power your digital business. Free to get started, and pay-as-you-go on all plans.