I'm new to react and I've just started learning about hooks and context.
I am getting some data from an API with the following code:
const getScreen = async uuid => {
const res = await axios.get(
`${url}/api/screen/${uuid}`
);
dispatch({
type: GET_SCREEN,
payload: res.data
});
};
Which goes on to use a reducer.
case GET_SCREEN:
return {
...state,
screen: action.payload,
};
In Screen.js, I am calling getScreen
and sending the UUID
to show the exact screen. Works great. The issue I am having is when I am trying to fetch the API (every 3 seconds for testing) and update the state of nodeupdated
based on what it retrieves from the API. The issue is, screen.data
is always undefined (due to it being asynchronous?)
import React, {
useState,
useEffect,
useContext,
} from 'react';
import SignageContext from '../../context/signage/signageContext';
const Screen = ({ match }) => {
const signageContext = useContext(SignageContext);
const { getScreen, screen } = signageContext;
const [nodeupdated, setNodeupdated] = useState('null');
const foo = async () => {
getScreen(match.params.id);
setTimeout(foo, 3000);
};
useEffect(() => {
foo();
setNodeupdated(screen.data)
}, []);
If I remove the [] is does actually get the data from the api ... but in an infinate loop.
The thing is this seemed to work perfectly before I converted it to hooks:
componentDidMount() {
// Get screen from UUID in url
this.props.getScreen(this.props.match.params.id);
// Get screen every 30.5 seconds
setInterval(() => {
this.props.getScreen(this.props.match.params.id);
this.setState({
nodeUpdated: this.props.screen.data.changed
});
}, 3000);
}
Use a custom hook like useInterval
function useInterval(callback, delay) {
const savedCallback = useRef();
useEffect(() => {
savedCallback.current = callback;
});
useEffect(() => {
function tick() {
savedCallback.current();
}
let id = setInterval(tick, delay);
return () => clearInterval(id);
}, [delay]);
}
Then in your component
useInterval(() => {
setCount(count + 1);
}, delay);
Dan Abramov has a great blog post about this
https://overreacted.io/making-setinterval-declarative-with-react-hooks/
You can use some thing like this. Just replace the console.log with your API request.
useEffect(() => {
const interval = setInterval(() => {
console.log("Making request");
}, 3000);
return () => clearInterval(interval);
}, []);
Alternatively, Replace foo
, useEffect
and add requestId
const [requestId, setRequestId] = useState(0);
const foo = async () => {
getScreen(match.params.id);
setTimeout(setRequestId(requestId+1), 3000);
};
useEffect(() => {
foo();
setNodeupdated(screen.data)
}, [requestId]);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.