Reputation: 7092
I have this small React component, and it doesn't seem to be setting the state of my authToken in the useEffect() call.
Here is my code:
const App = ({ personId, buildingId }) => {
const [authToken, setAuthToken] = useState();
useEffect(() => {
axios.post('/api/auth/' + personId + '/location/' + buildingId, {
headers: {
'Content-Type': 'application/json',
}
}).then((res) => {
setAuthToken(res.data);
})
}, []);
return (
<Editor
init={{
tinydrive_token_provider: function (success, failure) {
success({ token: authToken.token });
}}
/>
)
}
export default App;
Do I need to set it some other way?
Thanks!
Upvotes: 0
Views: 70
Reputation: 53536
Try this:
const App = ({ personId, buildingId }) => {
const handleTokenProvider = useCallback((success, failure) => {
axios.post('/api/auth/' + personId + '/location/' + buildingId, {
headers: {
'Content-Type': 'application/json',
}
}).then((res) => {
if (res && req.data && req.data.token) {
success(res.data.token);
} else {
failure("Authentication failed");
}
}).catch(err => {
failure(err);
});
}, [personId, buildingId]);
return (
<Editor
init={{
tinydrive_token_provider: handleTokenProvider
}}
/>
);
}
export default App;
The code above assumes a few things :
tinydrive_token_provider
detects when it's value change and calls the function again when it does. If it does not, then there must be a way to update the token. And if it still does not, then unmounting the component and re-mounting it again will force recreating it.useState
) or a reference (useRef
) but there should be a way to call success
/failure
without requiring a component update.App
component, a request will be made, even if you just got the token for the same props. Having a way to store this token in a cache (e.g. localStorage
) could greatly improve performance on refresh.If you need to have access to the token elsewhere than the Editor
, this would also work :
// this function get be in a separate module!
const fetchAuthToken = (personId, buildingId) => new Promise((resolve, reject) => {
// TODO : check some cache first, and resolve if a
// previous token already exists and is not expired, etc.
axios.post('/api/auth/' + personId + '/location/' + buildingId, {
headers: {
'Content-Type': 'application/json',
}
}).then((res) => {
if (res?.data?.token) {
resolve(res.data.token);
} else {
reject("Authentication failed");
}
}).catch(err => {
reject(err);
});
});
const App = ({ personId, buildingId }) => {
const tokenPromise = useMemo(() =>
fetchAuthToken(personId, buildingId),
[personId, buildingId]
);
// DEBUG ONLY
useEffect(() => {
tokenPromise.then(token => {
console.log('Token for', personId, buildingId, 'is', token);
}, err => {
console.error('Failed to get token for', personId, buildingId);
console.error(err);
});
}, [tokenPromise, personId, buildingId]);
return (
<Editor
init={{
tinydrive_token_provider: (success, failure) => {
tokenPromise.then(success, failure);
}
}}
/>
);
}
export default App;
Upvotes: 1