Reputation: 2464
I am trying to use React context as a state manager in my React Native app.
Here's the context:
import React, { createContext, useState, useEffect } from "react";
import axios from "axios";
export const GlobalContext = createContext();
export const Provider = ({ children }) => {
const [tracksList, setTracksList] = useState([
{
track_list: []
}
]);
useEffect(() => {
axios
.get(
`https://cors-anywhere.herokuapp.com/https://api.musixmatch.com/ws/1.1/chart.tracks.get?page=1&page_size=10&country=us&f_has_lyrics=1&apikey=${
process.env.REACT_APP_MM_KEY
}`
)
.then(res => {
setTracksList([
{
track_list: res.data.message.body.track_list
}
]);
})
.catch(err => console.log(err));
}, []);
return (
<GlobalContext.Provider value={[tracksList, setTracksList]}>
{children}
</GlobalContext.Provider>
);
};
export const Consumer = GlobalContext.Consumer;
Child component. Here I'd like to make an API call to get users and set this users field to global context. I can get context value from consumer, but how to set the new one?
import React, { useContext } from "react";
import { GlobalContext } from "../../context/context";
const Demo = () => {
const contextValue = useContext(GlobalContext);
console.log(contextValue, "Context outside from JSX");
return <div>Content</div>;
};
export default Demo;
So, is it possible to add new value to React context from every child component, like in Redux? Thanks in advance!
Upvotes: 4
Views: 2735
Reputation: 1201
You could use the useReducer
effect to achieve Redux reducers:
// Create context
export const ApiContext = React.createContext();
// Create some reducer function
const reducer = (state, action) => {
if (action.type === 'some action name') {
return {
...state,
report: action.payload,
};
}
return state;
};
// Overwrite a context provider
const Provider = ({ children }) => {
const [state, dispatch] = React.useReducer(reducer, {});
return (
<ApiContext.Provider
value={{
...state,
dispatch,
}}
>
{children}
</ApiContext.Provider>
);
};
Then you could use in components as follows:
const Component = () => {
const { dispatch, report } = React.useContext(ApiContext);
React.useEffect(() => {
const asyncPost = async () => {
const response = await fetch('some endpoint', {
method: 'POST',
});
const payload = await response.json();
// This will call a reducer action and update a state
dispatch({
type: 'some action name',
payload,
});
}
}, []);
...
};
So when Component
is mounted, the state would be an empty object. Then when you update the state using the some action name
action, the state becomes { report: some data from fetch }
.
Upvotes: 3