I have a global token variable that I want to update whenever I make an API request with axios. The problem that I am having is how to update the the token variable since the axios request is not made in a functional component, so I am not able to take advantage of React hooks when making such request.
const logInUser = async (usernameOrEmail, password) => {
//const myContext = useContext(AppContext);
//^ gives an error b/c it's a react hook
axios
.post(
`https://jellybackend.herokuapp.com/authenticate`, {
username: usernameOrEmail,
password: password,
})
.then((response) => {
//myContext.setToken(response.data.token); //update token set , error since not a functional component
console.log(response);
tokenGlobal = response.data.token
})
.catch((error) =>
console.log(error)
);
};
I am making my token a global state, so I have the hook defined in App.js, as seen below
export default function App() {
//define global variable of token
const [token, setToken] = useState("");
const userSettings = {
token: "",
setToken,
};
return (
<AppContext.Provider value={userSettings}>
...
</AppContext.Provider>
);
}
Any idea on how to update my global state variable, or how to refactor my code would be very appreciated!
What I want eventually to happen is that whenever a user logs in, the token is updated, since that is what is returned from the axios post request.
The button below is how a user logs in
function LoginScreen(props) {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const myContext = useContext(AppContext);
return (
...
<Button
onPress={ () => {logInUser(email, password);} //I want to update the token here...
w="40%"
py="4"
style={styles.button}
>
CodePudding user response:
A very simple and trivial refactor would be to pass callback functions to the logInUser
utility.
Example:
const logInUser = async (usernameOrEmail, password, onSuccess, onFailure) => {
axios
.post(
`https://jellybackend.herokuapp.com/authenticate`, {
username: usernameOrEmail,
password: password,
})
.then((response) => {
onSuccess(response);
console.log(response);
})
.catch((error) =>
onFailure(error);
console.log(error);
);
};
...
function LoginScreen(props) {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const myContext = useContext(AppContext);
const successHandler = response => myContext.setToken(response.data.token);
const failureHandler = error => myContext.setToken(null);
return (
...
<Button
onPress={() => logInUser(email, password, successHandler, failureHandler)}
w="40%"
py="4"
style={styles.button}
>
...
</Button>
...
);
}
CodePudding user response:
You could setup your axios call in a module that can then return the value that you would like to store in global state.
Your axios call doesn't have to exist within a functional component per se, but it would need to be imported/called within one for this solution.
So, you could change your axios call to be within a module function that could then be exported, say globalsapi.js, then imported to your functional component:
exports.logInUser = async () => {
const globalData = await axios
.post(
`https://jellybackend.herokuapp.com/authenticate`, {
username: usernameOrEmail,
password: password,
});
const token = await globalData.data.token;
return token;
}
Now, wherever you decide to call the setToken state update, you can just import the function and set the global token:
import { logInUser } from './globalsapi';
logInUser().then(data => {
myContext.setToken(data);
});
You could pass whatever parameters needed to the logInUser function.