I am creating a crypto react application and just trying to figure something out in which a function is returning an empty array when I update one of the state values. I am thinking it is a race condition. It works until there is a state change. Please see my code below:
So I have a state object. And it is returning an array of currencies by default based on the selectedCurrencyState.selectedFromCurrency value, which is a state value. This function basically needs to determine the quoteAsset before returning the object that contains the array of baseCurrencies. swapInfo
is the state value containing the mock data. The mock data is nested like so:
const getBaseCurrencies = () => {
const filteredQuoteAssetObj = selectedCurrencyState.selectedFromCurrency
&& swapInfo.find(item =>
item.quoteAsset === selectedCurrencyState.selectedFromCurrency);
const currencies = filteredQuoteAssetObj
&& filteredQuoteAssetObj.baseAssets.map(item => item.baseAsset);
return currencies;
}
Here is the mock data that I am using:
Like I said, it works until the state change of selectedCurrencyState.selectedFromCurrency
(switch state from USD to SHIB). Afterwards, it returns an empty array. By default I have the state set to USD as the selectedFromCurrency
.
Any help or input is appreciated. Thanks guys!
--UPDATED-- Here is the way I am updating the state by the way. I am using a functional component therefore, using useState.
const [swapInfo, setSwapInfo] = useState([]);
const [fromCurrencies, setFromCurrencies] = useState([]);
const [selectedCurrencyState, setSelectedCurrencyState] = useState({ selectedToCurrency: null, selectedFromCurrency: null });
const [transactionType, setTransactionType] = useState(TRANSACTION_TYPES.BUY);
useEffect(() => {
getSwapPairs()
.then((res) => {
setSwapInfo(res.data);
setFromCurrencies(res.data.map(item => item.quoteAsset));
if (transactionType === 'BUY') {
setSelectedCurrencyState({ ...selectedCurrencyState, selectedFromCurrency: localStorage.getItem('fromCurrency') || 'USD', selectedToCurrency: symbol || localStorage.getItem('toCurrency') });
}
setTransactionType(localStorage.getItem('transactionType', transactionType) || TRANSACTION_TYPES.BUY);
}, []);
const handleInvertSelectedAssets = (fromCurrency, toCurrency) => {
setSelectedCurrencyState({ ...selectedCurrencyState, selectedFromCurrency: toCurrency, selectedToCurrency: fromCurrency });
localStorage.setItem('toCurrency', fromCurrency);
localStorage.setItem('fromCurrency', toCurrency);
};
Here is where I switch the transactionType:
const handleTransactionTypeChange = (type) => {
if (transactionType !== type) {
setTransactionType(type);
handleInvertSelectedAssets(selectedCurrencyState.selectedFromCurrency, selectedCurrencyState.selectedToCurrency);
localStorage.setItem('transactionType', type);
setAmountState({ toCurrencyAmount: '', fromCurrencyAmount: '' });
}
};
CodePudding user response:
Feel like your problem lies in the way you update your state.
Maybe there is a typo on the updated selectedCurrencyState.selectedFromCurrency
or maybe swapInfo
is somehow updated in an invalid way ?
Could you fill in more info about how your state is managed ?
CodePudding user response:
When you update state in React,
The following should not be done
this.state = {a:"red", b:"blue"};
if( this.state.b == "blue" ) {
this.setState({a: "green" });
}
Instead, do
this.setState((prevState)=>(
{a: (prevState.b=="blue")? "green": "red" }
));
In other words, state updates that depend on its previous value, should use the callback argument of the setState
.
Eg: selectedCurrencyState
depends on transactionType
.
You can store both (or all state properties) as a single object.