React native state not updating function - reactjs

React native state not updating. Location in alert returns empty.
Help me please
function Home({ route, navigation }) {
const [location, setLocation] = useState('');
const _appStart = () => {
_location();
}
const _location = () => {
setLocation("Konum Ekle");
alert(location);
}
React.useEffect(() => {
const unsubscribe = navigation.addListener('focus', () => {
_appStart();
});

try this
const _location = useCallback(()=>{
setLocation('Hi')
},console.warn(location)
)
instead of
const _location = () => {
setLocation("Konum Ekle");
alert(location);
}
Basically setState is asynchronous. So call your alert in callback of setLocation, so once setLocation is complete your alert will comes in action.

Related

React component is not loading props after history.goback()

I have a component which is updating states on page load with useeffect. But when i use history.goback() function to go back from a component to my bank component useeffect is not working. Here my code ;
bottomnavigator.js :
const goBack = () => {
if (props.history.location.pathname !== "/app/phone" && props.history.location.pathname !== "/") {
props.history.goBack();
}
};
bank.js :
const [transactions, settransactions] = useState([]);
const [bankBalance, setbankBalance] = useState(0);
const getBankData = async () => {
if (props.location.state) {
const res = await Nui.post(props.location.state, {});
if (res) {
setbankBalance(res);
}
}
}
const getTransactionData = async () => {
if (props.location.state) {
const res = await Nui.post('GET_BANK_TRANSACTIONS', {});
if (res) {
settransactions(res);
}
}
}
useEffect(() => {
getBankData();
getTransactionData();
}, []);
The issue is that you have listed "no dependencies" ([]) in your useEffect, so it will run once at the beginning and then never again. You should either omit the dependencies like so:
useEffect(() => {
getBankData();
getTransactionData();
});
Or list the correct set of dependencies like so: (I'm guessing here based on your code, but hopefully I got it right)
useEffect(() => {
getBankData();
getTransactionData();
}, [props.location.state]);

how to fetch data from webservice in REACT useEffect function and send it to props object?

I'm trying to fetch data from a webservice to a child component. It looks like Data are fetched ok in console.log() inside useEffect function. I'm not able to work with them in higher function scope. I'd like to access fetched data in the child component (PComponent) through the props object.
Thank you for any advice.
function App(props) {
let data = undefined;
useEffect( () => {
console.log('UseEffect');
const fetchData = async () => {
const result = await axios.get(someUrl)
data = result.data;
console.log('result',data);
return data;
};
data = fetchData();
}, []);
return (
<PComponent settings = {data}/>
);
}
export default App;
Try useState hook to store your data. Any state update will rerender the component and therefore data is passed to the child.
const App = (props) => {
const [data, setData] = React.useState()
const fetchData = async() => {
const result = await axios.get(someUrl)
setData(result);
};
// Fetch data when component mounted
useEffect( () => {
fetchData()
}, []);
return (
<PComponent settings={data}/>
);
}
export default App;
You have to use useState for state which can change in functional components. You can read about that on the React docs.
function App(props) {
const [data, setData] = useState(undefined);
useEffect(async () => {
console.log("useEffect running");
const fetchData = async () => {
const result = await axios.get(someUrl);
console.log(result.data);
return result.data;
};
setData(await fetchData());
}, []);
return <PComponent settings={data} />;
}

React async event handler. The safe way

Imagine a simple react component
const Upload: React.FC = () => {
const [done, setDone] = useState(false)
const upload = async () => {
await doSomeAsyncStuffHere()
setDone(true)
}
if(done) {
return <div>success</div>
}
return (
<button onClick={upload}>upload</button>
)
}
It looks fine at first glance. But what if upload function takes a long time to finish? What if user navigates to another view and the component gets unmounted? When the async task finishes will cause a state update on an unmounted component. This is a no-op and a possible memory leak. What should I do to prevent it?
One way of going about it is to create a ref that you set to false when the component is unmounted, and check against this before setting the result of your asynchronous code in the component state.
Example
const Upload: React.FC = () => {
const isMounted = useRef(true);
const [done, setDone] = useState(false)
const upload = async () => {
await doSomeAsyncStuffHere()
if (isMounted.current) {
setDone(true)
}
}
useEffect(() => {
return () => {
isMounted.current = false;
};
}, []);
if(done) {
return <div>success</div>
}
return (
<button onClick={upload}>upload</button>
)
}

Reload component with react hooks

I would like to ask you how to reload a component after modifying the data of a form, then I have my component:
export default function MyComponent() {
const url = "/api/1";
const [resData, setResData] = useState(null);
useEffect(() => {
const jwt = getJwt();
const fetchData = async () => {
const resP = await axios(url);
setResData(resP.data);
};
fetchData();
}, []);
return <EditComponent={resData} />
}
This component passes my data to the "EditCompoent" child component in which there is a form that is filled with data from the parent component that I can modify in which there is a save button that when I click allows me to send the modified data to my beckend:
const handleConfirm = () => {
axios.put(url, data).then((res) => {
//Reload Component
})
}
I would like to be able to reload the parent component as soon as this works is successful what could I do? I don't want to reload the whole page I just want to reload the parent component that is "MyComponent", I hope I have well posed the problem.
I'd pass the whole useEffect callback down so that handleConfirm can call it again after the axios.put, after which the resData state in the parent will be updated:
export default function MyComponent() {
const url = "/api/1";
const [resData, setResData] = useState(null);
const tryLoginJWT = () => {
const jwt = getJwt();
const resP = await axios(url);
setResData(resP.data);
};
useEffect(tryLoginJWT, []);
return <EditComponent {...{ resData, tryLoginJWT }} />
}
const handleConfirm = () => {
axios.put(url, data)
.then(tryLoginJWT)
.catch(handleErrors); // don't forget to catch here in case there's a problem
}

How to cleanup async tasks created outside useEffect

I created a custom hook useFetch that returns a fetch function that I can use in other components. It uses a promise to fetch some data inside. My goal is to clean up the pending promise, if the component, that uses this custom hook gets unmounted.
How would I do it? I tried something using useRef, but without success yet. Still getting the Can't perform a React state update on an unmounted component. warning.
const useFetch = (url) => {
const [isFetching, setIsFetching] = useState(false)
const handler = useRef(null)
useEffect(() => () => {
if (handler.current !== null) {
handler.current.cancel()
}
}, [])
return (options) => {
handler.current = window.fetch(url, options)
setIsFetching(true)
return handler.current.then(() => {
handler.current = null
setIsFetching(false)
})
}
}
export default () => {
const fetchData = useFetch('www.tld')
useEffect(() => {
fetchData({}).then(() => console.log('done'))
}, [])
return null
}
Notice that the promise in this example is cancelable via .cancel() (so thats not a problem here).
Return cancel() as bound callback from your hook. Then it would be up to consumer to stop it:
const useFetch(url) {
const [isFetching, setIsFetching] = useState(false)
const handler = useRef(null)
function run(options) {
handler.current = window.fetch(url, options)
setIsFetching(true)
...
}
function cancel() {
if(handler.current) {
handler.current.cancel()
}
}
return {run, cancel}
}
...
function OtherComponent({userId}) {
const [userData, setUserData] = useState(null);
const {run, cancel} = useFetch(`/user/${userId}`);
useEffect(() => {
run(options).then(setUserData);
return cancel; // it's up to consumer code to stop request
}, [userId]);
}

Resources