Я пишу простую страницу реагирования, где данные пользователя могут быть получены из одного API и несколько раз переданы другому API с некоторыми изменениями.
export default function User() {
const [userid, setUserId] = useState("");
const [userData, setUserData] = useState({});
const synchToLocation=(loc)=>{
setUserData((userData)=>({...userData,id:1234,location:loc}));
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(userData)
};
fetch("http://localhost:8080/api/v1/synch" , requestOptions);
}
const handleSynch = () => {
synchToLocation(1);
synchToLocation(2);
synchToLocation(3);
};
const fecthUser = (event) => {
event.preventDefault();
console.info(userid);
fetch("http://localhost:8080/api/v1/synch/emp?id = " + userid).then((result) =>
result.json().then((e) => { setUserData({...userData,id:e.id,firstName:e.firstName,lastName:e.lastName,role:e.role,location:e.location,status:e.status});
})
);
};
return (
<Container>
<TextField
id = "id"
label = "user id"
value = {userid}
onChange = {(e) => setUserId(e.target.value)}
fullWidth
required
></TextField>
<Button
variant = "contained"
color = "secondary"
type = "submit"
onClick = {fecthUser}
>
Search
<SearchOutlined />
</Button>
<Box>
<Button variant = "contained" color = "secondary" onClick = {handleSynch}>
Synch
</Button>
</Box>
</Container>
);
}
У меня одно текстовое поле и две кнопки (поиск и синхронизация). Ожидание:
Фактический результат:
Пожалуйста, предложите мне лучший способ добиться этого.
Хуки и useEffect() позволят вам обновить локальное состояние и выполнить повторный рендеринг на основе этого обновленного состояния.
См.: https://reactjs.org/docs/hooks-effect.html
const SimpleComp = (userName, fetchUserAPI, fetchLocalParams) => {
const [userData, setUserData] = useState(null);
const [localParams, setLocalParams] = useState(null);
useEffect(() => {
setUserData( fetchUserAPI(userName) );
}, []);
useEffect(() => {
setLocalParams( fetchLocalParams(userData) );
}, [userData]);
return (
<>UserData: {userData} localParams: {localParams}</>
);
};
export default SimpleComp;
Начальное состояние для обоих хуков равно null. Первый useEffect() с пустыми параметрами наблюдения ([]) будет вызываться при загрузке. Второй useEffect() отслеживает хук: userData. Когда пользовательские данные изменяются; этот useEffect будет вызываться с обновленным состоянием. Первый вызывает fetchUserData при загрузке. Это обновляет userData до возврата из вызова API. Это устанавливает данные пользователя с новым значением. Затем будет вызван второй useEffect, потому что userData-Hook изменил состояние. Этот useEffect вызывает fetchLocalParametersAPI и устанавливает значение этого хука в возвращаемые данные.
Все эти изменения в состоянии хука вызывают повторный рендеринг после того, как все useEffects() были оценены. В это время; все переменные Hook должны быть актуальными и отображать локальные параметры на основе пользовательских данных.
Если вам нужно использовать подход кнопки синхронизации; затем создайте onClick, который устанавливает новый хук userName из текстового ввода и обновляет userName onClick(). Просто создайте еще один useEffect, который отслеживает userName и вызывает fetchUserDataAPI с новым именем пользователя. Это обновит хук userData, который затем вызовет fetchLocalParams при изменении userData.
ОП спросил, есть ли лучший способ подойти к этому. Именно для этого варианта использования и нужны хуки. Разрешение нескольких операций на основе обновленного состояния перед повторным рендерингом.
Извини. ОП спросил о лучших способах сделать это. Я больше никогда не отвечу ни на один вопрос StackOverflow.
Проблема здесь. Поскольку setState работает асинхронно, поэтому после setUserData тело запроса иногда использует старые пользовательские данные вместо новых пользовательских данных, которые вы установили ранее.
const synchToLocation=(loc)=>{
setUserData((userData)=>({...userData,id:1234,location:loc}));
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(userData)
};
fetch("http://localhost:8080/api/v1/synch" , requestOptions);
}
Вы должны изменить тело свойства объекта на
body:JSON.stringify({...userData,id:1234,location:loc})
Я не понимаю, как этот «ответ» приближается к заданному вопросу или проблемам, которые есть у ОП.