I'm send some settings data in useEffect:
const [settingsData, setSettingsData] = useState([]);
const [settingsLoading, setSettingsLoading] = useState(true);
useEffect(() => {
if (isAuth) {
apiClient
.get("api/v1/page-data/settings")
.then((response) => {
setSettingsData(response.data);
setSettingsLoading(false);
})
.catch((error) => console.error(error));
}
}, []);
And create useStates for two keys inputs with data from backend:
const [publicKey, setPublicKey] = useState(
settingsData?.data?.user_data?.public_key
);
const [secretKey, setSecretKey] = useState(
settingsData?.data?.user_data?.secret_key
);
There is an inputs:
<input
value={publicKey}
onChange={(e) => setPublicKey(e.target.value)}
placeholder="PublicKey"
/>
<input
value={secretKey}
onChange={(e) => setSecretKey(e.target.value)}
placeholder="SecretKey"
/>
When page is loaded i'm just see empty inputs, looks like useState assign my backend property when it's undefined. How can i assign backend data to useState if this hook initialize initial value before my settings data is loaded from backend?
CodePudding user response:
Your key related initial states are set to undefined
because the data is not available when they are created. There are a few ways to solve that, here are a couple:
- You can set those key related values at the same time you set your data object instead of trying to derive them
const [settingsData, setSettingsData] = useState([]);
const [settingsLoading, setSettingsLoading] = useState(true);
const [publicKey, setPublicKey] = useState('');
const [secretKey, setSecretKey] = useState('');
useEffect(() => {
if (isAuth) {
apiClient
.get("api/v1/page-data/settings")
.then(({ data }) => {
setSettingsData(data);
setSettingsLoading(false);
setPublicKey(data.user_data.public_key);
setSecretKey(data.user_data.secret_key);
})
.catch((error) => console.error(error));
}
}, []);
- A less optimal option would be to use another
useEffect
to update your key telated states
const [settingsData, setSettingsData] = useState([]);
const [publicKey, setPublicKey] = useState('');
const [secretKey, setSecretKey] = useState('');
useEffect(() => {
if (settingsData) {
setPublicKey(settingsData.user_data.public_key);
setSecretKey(settingsData.user_data.secret_key);
}
}, [settingsData]);
- a third option is to make only the initial state of the inputs derived from the returned data and use short circuiting to manage the value
const [settingsData, setSettingsData] = useState([]);
const [settingsLoading, setSettingsLoading] = useState(true);
const [publicKey, setPublicKey] = useState('');
const [secretKey, setSecretKey] = useState('');
const publicK = settingsData?.data?.user_data?.public_key;
const secretK = settingsData?.data?.user_data?.secret_key;
useEffect(() => {
if (isAuth) {
apiClient
.get("api/v1/page-data/settings")
.then(({ data }) => {
setSettingsData(data);
setSettingsLoading(false);
setPublicKey(data.user_data.public_key);
setSecretKey(data.user_data.secret_key);
})
.catch((error) => console.error(error));
}
}, []);
// inputs will start with the values from const but once you write anything
// in the input it will change to the managed value in state
<input
value={publicKey || publicK}
onChange={(e) => setPublicKey(e.target.value)}
placeholder="PublicKey"
/>
<input
value={secretKey || secretK}
onChange={(e) => setSecretKey(e.target.value)}
placeholder="SecretKey"
/>