Currently I have two files, one is being used to fetch and get the data response. The other js file is to import these results in a function. I would like to export this last function so I could use it in other files.
api.js
import axios from 'axios';
const url = 'data/data.json';
const cars = 'data/cars.json';
export const fetchData = () => {
return axios.get(url)
.then(response => {
return response.data
})
}
export const fetchCars = () => {
return axios.get(cars)
.then(response => {
return response.data
})
}
import.js
See: export const details
import { fetchData, fetchCars } from './api';
let fetchingData = fetchData();
let fetchingCars = fetchCars();
// I want to export the below functionality:
fetchingData.then((result) => {
// I will be doing stuff here
console.log(result);
})
export const details = () => {
fetchingCars.then((result) => {
// I will be doing stuff here
console.log(result);
})
}
// And be able to console.log the results out of that exported function. Since I will need to update DOM values based on the API results.
console.log(details);
importCars.js
import { details } from './import'
function example() {
// do something
details();
}
Just change the fetchData in api.js as below,
export const fetchData = () => {
return axios.get(url)
}
And in import.js use result.data instead of result while logging like below,
fetchingData.then((result) => {
// I will be doing stuff here
console.log(result.data);
})
Related
I've created a simple useFetch custom hook which allows me to call any Url I want :
import React, { useState, useEffect } from 'react';
export default function useFetch(url) {
console.log(url)
const [data, setData] = useState([]);
useEffect(() => {
fetch(url)
.then((response) => {
if (response.ok) return response.json();
setData([]);
})
.then((data) => {
setData(data)})
.catch((err) => {
console.error(err);
setData([]);
});
}, [url]);
return { data} ;
}
In my Main component I'm loading a static list of items.( via useEffect with [] becuase it's static)
I currently do it via :
export function Courses() {
const [langs, setLangs] = useState([]);
useEffect(() => {
getData(config.url).then((f) => setLangs(f));
}, []);
...
Where getData is:
export function getData(uri) {
return fetch(uri).then(response =>
response.json()
);
}
The problem is that I can't (don't know how) I can use my useFetch here becuase it can't be inside useEffect , and that's why I've created the additional getData method.
ps -
In other "details" component I use useFetch perfectly fine :
export default function Details({ langId }) {
const { data: teachers } = useFetch(`${config.url}/${langId}`);
...
The problem is only in the main component where I don't want to fetch manually . I want to use my useFetch. How can I do that ?
I want that Courses will load the static list only once via useFetch
One possible option is to cache the fetch response (I didn't test the code)
import React, { useState, useEffect } from 'react';
const cache = {};
export default function useFetch(url, useCache=false) {
console.log(url)
const [data, setData] = useState([]);
useEffect(() => {
if (useCache && cache[url]) {
setData(cache[url]);
} else {
fetch(url)
.then((response) => {
if (response.ok) {
const responseData = await response.json();
if (useCache) cache[url] = responseData;
return responseData;
}
setData([]);
})
.then((data) => {
setData(data)})
.catch((err) => {
console.error(err);
setData([]);
});
}
}, [url]);
return { data} ;
}
You can use useRef if you want to keep the hooks as a pure function
i'm newbie here, i'm stuck. i want to change value from false to true, to stop shimmering when data sucessfully to load.
i have action like this
import axios from "axios";
import { CONSTANT_LINK } from "./constants";
import { GET } from "./constants";
import { ERROR } from "./constants";
import { connect } from 'react-redux';
export const addData = () => {
return (dispatch) => {
axios
.get(CONSTANT_LINK)
.then((res) => {
dispatch(addDataSuccess(res.data));
})
.catch((err) => {
dispatch(errorData(true));
console.log("error");
});
};
};
const addDataSuccess = (todo) => ({
type: GET,
payload: todo,
});
const errorData = (error) => ({
type: ERROR,
payload: error,
});
and this is my homepage which influential in this matter
const [shimmerValue, setShimmerValue] = useState(false)
useEffect(() => {
setShimmerValue(true)
dispatch(addData());
}, []);
<ShimmerPlaceholder visible={shimmerValue} height={20}>
<Text style={styles.welcomeName}>Welcome,Barret</Text>
</ShimmerPlaceholder>
i dont understand how it works
You can pass callback like this
const [shimmerValue, setShimmerValue] = useState(false);
const updateShimmerValue = () => {
setShimmerValue(true);
}
useEffect(() => {
// setShimmerValue(true) // remove this from here
dispatch(addData(updateShimmerValue)); // pass callback as param here
}, []);
Callback call here like
export const addData = (callback) => {
return (dispatch) => {
axios
.get(CONSTANT_LINK)
.then((res) => {
....
callback(); // trigger callback like this here
})
.catch((err) => {
....
});
};
};
you can use it:
const [shimmerValue, setShimmerValue] = useState(false)
useEffect(() => {
setState(state => ({ ...state, shimmerValue: true }));
dispatch(addData());
}, [shimmerValue]);
I'm trying to fetch data from Firebase, I implemented nearly same codes like my react native app but this time I'm facing some problems that I couldn't figure out.
import {db} from './firebase'
const formatMarketData = (data) =>{
let formattedData = [];
data.forEach(item=>{
const formattedItem = {
...item
}
formattedData.push(formattedItem);
});
return formattedData;
}
export const FirebaseService = async (id) => {
id=id.replace(/['"]+/g, "");
const historyKey="/coins/0/"+id
await
db.ref(historyKey)
.once('value')
.then(snapshot => {
const data = snapshot.val();
const formattedResponse= formatMarketData(data);
console.log(formattedResponse)
return formattedResponse
});
};
This function helps me to retrieve data from my firebase rtdb. The console.log functions works and writes as expected but when I'm trying to catch it in my News page it becomes undefined.
import React from 'react'
import { useState,useEffect } from 'react'
import { FirebaseService } from '../../Services/FirebaseService'
const NewList = ({id}) => {
const [data,setData] = useState([])
useEffect(()=>{
console.log(id)
const fetchMarketData = async () =>{
const marketData = await FirebaseService(id);
return setData(marketData);
}
fetchMarketData();
return () => {
}
},[])
return (
<div>
{data!==undefined?data.map((d)=>{return(<p>{d.id}</p>)})
:<p>no data yet</p>}
</div>
)
}
export default NewList
I'm missing something but I can't notice. Another view might be helpful.
Define formattedResponse at start of function and return it at very end.
I have edited you function
import {db} from './firebase'
const formatMarketData = (data) =>{
let formattedData = [];
data.forEach(item=>{
const formattedItem = {
...item
}
formattedData.push(formattedItem);
});
return formattedData;
}
export const FirebaseService = (id) =>{
let formattedResponse = [];
id=id.replace(/['"]+/g, "");
const historyKey="/coins/0/"+id
await
db.ref(historyKey)
.once('value')
.then(snapshot => {
const data = snapshot.val();
formattedResponse=
formatMarketData(data);
console.log(formattedResponse)
})
return formattedResponse
};
I want to make static generation for top products with getStaticProps.
now a section of my rendering is not needed to static generation. for example: comments, related products.
full code:
export default function Gift(props) {
let [relatedProducts, setRelatedProducts] = useState([]);
const getRelatedProducts = () => {
api.get(`gift/id/${props.id}/relateds/count/10`).then(res => {
console.log(res.data.data);
setRelatedProducts(res.data.data)
})
}
//called n times. looping !!!
getRelatedProducts();
return (
<GiftProvider value={props}>
<ProductPage/>
<RelatedProducts title="related products" products={relatedProducts}/>
<ProductGeneralProperties/>
<ProductComment/>
</GiftProvider>
);
}
export async function getStaticPaths() {
const gifts = await getTopGifts()
const paths = gifts.map((gift) => ({
params: {slug: gift.slug}
}))
return {paths, fallback: 'blocking'}
}
export async function getStaticProps(context) {
const slug = context.params.slug
const gift = await getGiftWithSlug(slug)
return {
props: gift,
}
}
but with below code my codes renders multi times:
export default function Gift(props) {
let [relatedProducts, setRelatedProducts] = useState([]);
const getRelatedProducts = () => {
api.get(`gift/id/${props.id}/relateds/count/10`).then(res => {
console.log(res.data.data);
setRelatedProducts(res.data.data)
})
}
getRelatedProducts();
You can use useEffect hook to call the api
useEffect(() => {
const getRelatedProducts = () => {
api.get(`gift/id/${props.id}/relateds/count/10`).then(res => {
console.log(res.data.data);
setRelatedProducts(res.data.data)
})
}
getRelatedProducts();
},[])
So decided to use redux-thunk and I have a problem to write a function in my actions and reducer. Actually function looks like this:
async getData() {
if (this.props.amount === isNaN) {
return;
} else {
try {
await fetch(
`https://api.exchangeratesapi.io/latest?base=${this.props.base}`,
)
.then(res => res.json())
.then(data => {
const date = data.date;
const result = (data.rates[this.props.convertTo] * this.props.amount).toFixed(4);
this.setState({
result,
date,
});
}, 3000);
} catch (e) {
console.log('error', e);
}
}
}
Also I already have action types
export const FETCH_DATA_BEGIN = 'FETCH_DATA_BEGIN';
export const FETCH_DATA_SUCCESS = 'FETCH_DATA_SUCCESS';
export const FETCH_DATA_FAIL = 'FETCH_DATA_FAIL';
and actions like this
export const fetchDataBegin = () => {
return {
type: actionTypes.FETCH_DATA_BEGIN,
};
};
export const fetchDataSuccess = data => {
return {
type: actionTypes.FETCH_DATA_SUCCESS,
data: data,
};
};
export const fetchDataFail = error => {
return {
type: actionTypes.FETCH_DATA_FAIL,
error: error,
};
};
And then comes the hard part for me where I don't know how to get the same result from function async getData(). I already have just this in my action :
export async function fetchData() {
return async dispatch => {
return await fetch(`https://api.exchangeratesapi.io/latest?base=${this.props.base}`)
.then(res => res.json())
.then(data => {
// <------------------- WHAT NEXT?
}
};
export function fetchData() {
return dispatch => {
fetch(`https://api.exchangeratesapi.io/latest?base=${this.props.base}`)
.then(res => res.json())
.then(data => dispatch(fetchDataSuccess(data)), e => dispatch(fetchDataFail(e)))
}
};
Now this code:
const date = data.date;
const result = (data.rates[this.props.convertTo] * this.props.amount).toFixed(4);
this.setState({
result,
date,
});
goes into your reducer
if(action.type === FETCH_DATA_SUCCESS) {
const date = action.data.date;
const rates = action.data.rates;
return { ...state, rates, date };
}
Now you can use the redux state in your component and make the rest of the calculations there (ones that need this.props).
To dispatch the fetchData action now, you do this.props.dispatch(fetchData()) in your react-redux connected component.
EDIT
Here's how you use the state in the component.
I'm assuming you have created the redux store. something like:
const store = createStore(rootReducer,applyMiddleware(thunk));
Now, you can use the react-redux library's connect function to connect the redux state to your component.
function mapStateToProps(state, ownProps) {
return {
date: state.date,
result: (state.rates[ownProps.convertTo] * ownProps.amount).toFixed(4);
}
}
function mapDispatchToProps(dispatch) {
return {
fetchData: () => dispatch(fetchData())
}
}
export default connect(mapStateToProps,mapDispatchToProps)(YourComponent)
You can use this Higher Order Component in your DOM now and pass the appropriate props to it:
import ConnectedComponent from "./pathTo/ConnectedComponent";
...
return <View><ConnectedComponent convertTo={...} amount={...} /></View>;
And, also inside YourComponent you can now read this.props.date and this.props.result and use them wherever you need to.
You might want to look at selectors in the future to memoize the state and reduce the performance cost of redux.