Im fetching data from api using axios, in the api https:/...?vs_currency=${currency}&...
I am trying to assign currency
value to api using redux. The problem is useSelector gives the undefined
value for the first time and i failed to fetch data from this api. But then useSelector works fine. Error display is https:/...?vs_currency=undefined&...
Here is the redux code
import { createSlice } from "@reduxjs/toolkit";
export const currencySlice = createSlice({
name: "currency",
initialState: {
currency: "usd", // first i have currency: null. but then i change it to avoid undefined value, but same result
},
reducers: {
selectCurrencyAndSymbol: (state, action) => {
state.currency = action.payload;
},
},
});
export const { selectCurrencyAndSymbol } = currencySlice.actions;
export const selectcurrency = (state) => state.currency.currency;
export default currencySlice.reducer;
Here is the useSelector code
importing stuff ...
function Carousel() {
const classes = useStyles();
const [trending, setTrending] = useState("");
const currencySelector = useSelector(selectcurrency);
const fetchTrendingCoins = async () => {
const data = await axios.get(TrendingCoins(currencySelector?.currency));
setTrending(data);
};
useEffect(() => {
fetchTrendingCoins();
}, [currencySelector.currency]);
...
I Also try to directly assign value for the first time
var currencyValue;
useEffect(() => {
currencyValue = !currencySelector.currency
? currencyValue === "pkr"
: currencyValue === "usd";
currencyValue = currencySelector?.currency;
fetchTrendingCoins();
}, [currencyValue]);
Here is the useDispatch code
importing stuff ...
function Header() {
const [currency, setCurrency] = useState("usd");
const [symbol, setsymbol] = useState("$");
const dispatch = useDispatch();
useEffect(() => {
if (currency === "pkr") setsymbol("Rs");
else if (currency === "usd") setsymbol("$");
dispatch(selectCurrencyAndSymbol({ currency, symbol }));
}, [currency]);
....
CodePudding user response:
//Here you can see that your sending in an
object {
currency: "usd",
symbol: "$"
}
selectCurrencyAndSymbol({currency, symbol})
Then in your useEffect you will have issues with the way your using setState
useEffect(() => {
if (currency === "pkr") setsymbol("Rs");
//else if (currency === "usd") setsymbol("$");
//here symbol will be $ as the state wouldnt have updated yet by the
//time the dispatch is envoked
dispatch(selectCurrencyAndSymbol({ currency, symbol }));
}, [currency]);
Your first soloution is to add symbol to your dependancy array which will cause the useEffect to be run when the symbol is updated
Second solution:
useEffect(() => {
let symbol = "";
if (currency === "pkr") symbol = "Rs";
else if (currency === "usd") symbol = "$"
dispatch(selectCurrencyAndSymbol({ currency, symbol }));
}, [currency]);
Then finally in your store state you have
initialState: {
//NOTE: This is not an object at first
currency: "usd",
},
reducers: {
selectCurrencyAndSymbol: (state, action) => {
//Here for example the action payload is {currency: "usd", symbol: "$"}
state.currency = action.payload;
},
Your solution would be if you want to keep the object approach:
initialState: {
currency: { currency: "usd", symbol: "$" };
},
reducers: {
selectCurrencyAndSymbol: (state, action) => {
state.currency = action.payload;
Or
state.currency.currency = action.payload.currency
state.currency.symbol = action.payload.symbol
},
OR
initialState: {
currency: "usd",
symbol: "$"
},
reducers: {
selectCurrencyAndSymbol: (state, action) => {
state.currency = action.payload.currency
state.symbol = action.payload.currency
},
However if you want to keep it as
initialState: {
currency: "usd"
},
//Then just send through the currency in your func like this
selectCurrencyAndSymbol(currency)
Please note then when you use your selector to get the state how you access the data is dependant on how it is defined so for example //Also just a heads up best practice is to use cam case here for selectcurrency should be selectCurrency
export const selectCurrency = (state) => state.currency.currency;
how we get the data could be const data = useSelector(selectCurrency) either data.currency if we followed the object approach other wise just data will work
I hope this gives you some insight
CodePudding user response:
Did you check the redux store with redux dev tool or console log. Can you see the currency value?
If currency might be null or undefined. Can't you put a if statement before fetchTrendingCoins function in useEffect? If there is no currency don't fetch.