#javascript #reactjs #typescript #function #react-hooks
Вопрос:
Я новичок в крючках react, здесь преобразование из класса(версия класса работает) в крючки, я не уверен, правильно ли я это сделал, потому что при использовании «тогда» в крючках говорится «Свойство», затем «не существует типа» (отправка: любая) => Обещание». ts(2339)»
это версия класса, которая работает:
import {
getGraph,
getFloorplan,
changeActiveCamera,
} from "../redux/actions";
const mapStateToProps = (state) => {
return {
currentSite: state.selection.currentSite,
currentCamera: state.selection.currentCamera,
};
};
function mapDispatchToProps(dispatch) {
return {
getGraph: (site) => dispatch(getGraph(site)),
getFloorplan: (site) => dispatch(getFloorplan(site)),
changeActiveCamera: (site, id) => dispatch(changeActiveCamera(site, id)),
};
}
loadGraph() {
if (this.props.currentSite) {
this.props.getFloorplan(this.props.currentSite.identif).then(() => {
console.log("Fetched floorplan");
this.props.getGraph(this.props.currentSite.identif).then(() => {
console.log("Fetched model", this.props.realGraph.model);
// new camera-related node amp; link status
if (this.props.currentCamera) {
this.props.changeActiveCamera(
this.props.currentSite.identif,
this.props.currentCamera.identif
);
}
});
});
}
}
это то, что я сделал, чтобы преобразовать его :
const dispatch = useDispatch();
const currentSite = useSelector((state) => state.selection.currentSite);
const currentCamera = useSelector((state) => state.selection.currentCamera);
const loadGraph = () => {
if (currentSite) {
dispatch(getFloorplan(currentSite.identif)).then(() => {
console.log("Fetched floorplan");
dispatch(getGraph(currentSite.identif)).then(() => {
console.log("Fetched model", realGraph.model);
// new camera-related node amp; link status
if (currentCamera) {
dispatch(
changeActiveCamera(
currentSite.identif,
currentCamera.identif
)
);
}
});
});
}
};
После просмотра видео, опубликованного в комментарии, я изменил код и получил новую ошибку: «Ошибка в диапазоне: максимальный размер стека вызовов превышен
в getFloorplan»
мой код:
const currentSite = useSelector((state) => state.selection.currentSite);
const currentCamera = useSelector((state) => state.selection.currentCamera);
const getFloorplan = (site) => dispatch(getFloorplan(site));
const getGraph = (site) => dispatch(getGraph(site));
const changeActiveCamera = (site, id) =>
dispatch(changeActiveCamera(site, id));
const loadGraph = () => {
if (currentSite) {
getFloorplan(currentSite.identif).then(() => {
console.log("Fetched floorplan");
getGraph(currentSite.identif).then(() => {
console.log("Fetched model", realGraph.model);
// new camera-related node amp; link status
if (currentCamera) {
changeActiveCamera(
currentSite.identif,
currentCamera.identif
);
}
});
});
}
};
Комментарии:
1. В оригинале
getGraph
есть обещание, которое означает, что вы можете использоватьthen
. Во втором примере (dispatch(getFloorplan(currentSite.identif)).then
) вы пытаетесь привязатьthen
dispatch
то, что не является обещанием. Я все еще не понимаю, почему вам нужно отправлять сообщения на каждом уровне.2. @Andy если бы вы преобразовали этот класс в хуки, как бы вы его преобразовали ?
3. не должен ли redux обновить что-то в своем состоянии после того, как вы выполнили отправку? и ваш компонент должен быть подписан на новый контент?
4. Это видео может помочь.
5. @Andy вы имеете в виду вот так: const getFloorplan = (сайт) => отправка(getFloorplan(сайт)); const getGraph = (сайт) =>> отправка(getGraph(сайт)); и внутри loadGraph удаление отправки?
Ответ №1:
Я очень сомневаюсь, что это простое решение сработает, но вот мои предложения по рефакторингу.
Пожалуйста, обратите внимание, что способ, которым был написан ваш старый класс, не является рекомендуемым способом написания redux. Конечно, код будет работать, но, по мнению многих людей, это не «правильный» способ.
Рефакторинг ваших действий
Я бы предпочел, чтобы мой код был написан так :
Ваш компонент.tsx
const currentSite = useSelector((state) => state.selection.currentSite);
const currentCamera = useSelector((state) => state.selection.currentCamera);
const dispatch = useDispatch();
const loadGraph = () => {
useEffect(() => {
if(currentSite)
getFloorPlan(currenSite.identif);
}, [ dispatch, currentSite.identif])
// dispatch is in the dependency array to stop make eslinter complain, you can remove it if you want, others are used to control the number of renders
};
Ваши действия.ts
// assuming you are using redux-thunk here
const getFloorplan = ( site : YourType ) => async dispatch => {
console.log("Fetched floorplan");
// remove await if getImage is a sync function, try with await first and remove if it doesn't fit
const response = await getImage(`api/graph/${site}/floorplan`, GET_FLOORPLAN);
dispatch(getGraph(response))
}
const getGraph = (site : YourType) => async dispatch => {
console.log("Fetched model", realGraph.model);
// new camera-related node amp; link status
if (currentCamera) {
changeActiveCamera(currentSite.identif,currentCamera.identif);
}
}
const changeActiveCamera = ( site: YourType, param: YourAnotherType ) => async dispatch => {
// your logic here
}
Комментарии:
1. мой план getfloor выглядит примерно так : функция экспорта getFloorplan(сайт) { возвращает getImage(
api/graph/${site}/floorplan
, GET_FLOORPLAN); };2. добавлены и обновлены
3. моя камера changeActiveCamera: функция экспорта Камера changeActiveCamera(сайт, камера) { возвращает getData(
api/cameras/${site}/${camera}
, CHANGE_CAMERA); } и моя камера getGrpah: функция экспорта getGraph(сайт) { возвращает getData(api/graph/${site}
, GET_ГРАФЫ); };4. и делая это, я получил следующее: Неперехваченная ошибка: Недопустимый вызов крючка. Крючки могут вызываться только внутри тела функционального компонента. Это может произойти по одной из следующих причин: 1. У вас могут быть несовпадающие версии React и средства визуализации (например, React DOM) 2. Вы можете нарушать правила хуков
5. я предполагал, что вы используете
redux-think
промежуточное программное обеспечение, мое решение не будет работать, если у вас не установлено это промежуточное программное обеспечение