I need to display JSX that depends on data from a network request. In my first attempt, the return statement was hit before the network request resolved
const showSubscriptions = () => {
const [methods, setMethods] = useState([]);
let subscriptionsRef = React.useRef({})
useEffect(() => {
const getCommunicatorMethods = async () => {
const { data } = await axios.get(
"/api/get_communicator_methods",
);
const routingKeys = await axios.get("api/get_routing_keys")
let routingKeysString = JSON.stringify(routingKeys.data)
let detections = routingKeysString.includes('Detection')
let zones = routingKeysString.includes('Zone')
let sensors = routingKeysString.includes('Sensor')
let notifications = routingKeysString.includes('Notification')
let system_configurations = routingKeysString.includes('SystemConfiguration')
let alerts = routingKeysString.includes('Alert')
subscriptionsRef.current = { 'subscribe_to_sensors': sensors, 'subscribe_to_zones': zones, 'subscribe_to_alerts': alerts, 'subscribe_to_notifications': notifications, 'subscribe_to_detections': detections, 'subuscribe_to_system_configurations': system_configurations }
console.log(subscriptionsRef.current)
setMethods([...Object.values(data)]);
};
console.log(subscriptionsRef.current) //[methods[0][0]]
getCommunicatorMethods();
}, []);
return methods
.filter((x) => x[0].includes("subscribe"))
.map((method) => (
<div key={method[0]}>
<span>{method[0].replaceAll("_", " ")}</span>
<Switch value={subscriptionsRef.current[method[0]]} onChange={handleChange(method[0])} />
</div>
));
};
Then I tried making the fn async so I can wait on the network request (I also had to get rid of the useEffect() so that await is at the top-level within the async function):
const showSubscriptions = () => {
const [methods, setMethods] = useState([]);
let subscriptionsRef = React.useRef({})
const getCommunicatorMethods = async () => {
const { data } = await axios.get(
"/api/get_communicator_methods",
);
const routingKeys = await axios.get("api/get_routing_keys")
let routingKeysString = JSON.stringify(routingKeys.data)
let detections = routingKeysString.includes('Detection')
let zones = routingKeysString.includes('Zone')
let sensors = routingKeysString.includes('Sensor')
let notifications = routingKeysString.includes('Notification')
let system_configurations = routingKeysString.includes('SystemConfiguration')
let alerts = routingKeysString.includes('Alert')
subscriptionsRef.current = { 'subscribe_to_sensors': sensors, 'subscribe_to_zones': zones, 'subscribe_to_alerts': alerts, 'subscribe_to_notifications': notifications, 'subscribe_to_detections': detections, 'subuscribe_to_system_configurations': system_configurations }
setMethods([...Object.values(data)]);
};
console.log(subscriptionsRef.current) //[methods[0][0]]
getCommunicatorMethods();
return methods
.filter((x) => x[0].includes("subscribe"))
.map((method) => (
<div key={method[0]}>
{/* {subscriptionsRef.current[method[0]]} */}
<span>{method[0].replaceAll("_", " ")}</span>
<Switch value={subscriptionsRef.current[method[0]]} onChange={handleChange(method[0])} />
</div>
));
};
The problem is that when I do this, I get the following error (as it seems React doesn’t allow returning JSX from an async component)
Objects are not valid as a React child (found: [object Promise]). If you meant to render a collection of children, use an array instead.