I am trying to update the context of a React App using data resulted from an API call to a REST API in the back end. The problem is that I can't synchronize the function.
I've tried this solution suggested in this blog post https://medium.com/@__davidflanagan/react-hooks-context-state-and-effects-aa899d8c8014 but it doesn't work for my case.
Here is the code for the textContext.js
import React, {useEffect, useState} from "react";
import axios from "axios";
var text = "Test";
fetch(process.env.REACT_APP_TEXT_API)
.then(res => res.json())
.then(json => {
text = json;
})
const TextContext = React.createContext(text);
export const TextProvider = TextContext.Provider;
export const TextConsumer = TextContext.Consumer;
export default TextContext
And this is the functional component where I try to access the data from the context
import TextProvider, {callTextApi} from "../../../../services/textService/textContext";
function Profile()
{
const text = useContext(TextProvider);
console.log(text);
const useStyles = makeStyles(theme => ({
margin: {
margin: theme.spacing(1)
}
}));
I can see the fetch request getting the data in the network section of the browser console but the context is not getting updated.
I've tried doing this in the textContext.js.
export async function callTextApi () {
await fetch(process.env.REACT_APP_TEXT_API)
.then(res => res.json())
.then(json => {
return json;
})
}
And I was trying to get the data in the Profile.js using the useEffect function as so
const [text, setText] = useState(null);
useEffect(()=> {
setText (callTextApi())
},[])
It's my first time using React.context and it is pretty confusing. What am I doing wrong or missing?
So, to use Context API in the app you need to follow the next steps: 1 create context - React.createContext () 2 provide context - YourContext.Provider 3 consume context - YourContext.Consumer, or for a functional component useContext (YourContext), or for a class component Class.contextType = YourContext.
For API request handling we used the Axios library. The React hooks are used here to manage state, and life cycle methods. By using this way, you can implement it in your React app functional component. This was just for the demonstration purpose of API handling in the React functional component.
If using the useContext hook, this will have the new value of the hook during the new render. To understand how React’s Context feature can help us, let’s look at a scenario where the React Context API would make things simpler for us.
► Go to the required Component and import the useContext hook from React and BlogContext from BlogContext.js - ► We use the context object (BlogContext) to get the context value (i.e. data) from the Provider component using the useContext method of React.
You have a lot of problems here. fetching
and changing should happen inside Provider
by modifying the value
property. useContext
receives an entire Context
object not only the Provider
. Check the following
//Context.js
export const context = React.createContext()
Now inside your Provider
import { context } from './Context'
const MyProvider = ({children}) =>{
const [data, setData] = useState(null)
useEffect(() =>{
fetchData().then(res => setData(res.data))
},[])
const { Provider } = context
return(
<Provider value={data}>
{children}
</Provider>
)
}
Now you have a Provider
that fetches some data
and pass it down inside value
prop. To consume it from inside a functional component
use useContext
like this
import { context } from './Context'
const Component = () =>{
const data = useContext(context)
return <SomeJSX />
}
Remember that Component
must be under MyProvider
UPDATE
{ children }
?Everything that goes inside a Component
declaration is mapped to props.children
.
const App = () =>{
return(
<Button>
Title
</Button>
)
}
const Button = props =>{
const { children } = props
return(
<button className='fancy-button'>
{ children /* Title */}
</button>
)
}
Declaring it like ({ children })
it's just a shortcut to const { children } = props
. I'm using children
so that you can use your Provider
like this
<MyProvider>
<RestOfMyApp />
</MyProvider>
Here children
is RestOfMyApp
Using createContext
. Let's assume the value
property of your Provider
is {foo: 'bar'}
const Component = () =>{
const content = useContext(context)
console.log(content) //{ foo : 'bar' }
}
That was a typo, I've changed to MyProvider
To access it from inside a class
based component
class Component extends React.Component{
render(){
const { Consumer } = context
return(
<Consumer>
{
context => console.log(contxt) // { foo: 'bar' }
}
</Consumer>
)
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With