해결된 질문
작성
·
173
1
안녕하세요 선생님 혼자 해보는 과정중에 질문이 있습니다.
import React from "react";
import Backdrop from "../components/Backdrop";
import Dialog from "../components/Dialog";
export const layoutContext = React.createContext({});
layoutContext.displayName = "LayoutContext";
export class Layout extends React.Component {
constructor(props) {
super(props);
this.state = {
dialog: null,
};
this.setDialog = this.setDialog.bind(this);
}
setDialog(dialog) {
this.setState({ dialog });
}
render() {
const value = {
dialog: this.state.dialog,
setDialog: this.setDialog,
};
return (
<layoutContext.Provider value={value}>
{this.props.children}
</layoutContext.Provider>
);
}
}
export const DialogContainer = () => (
<layoutContext.Consumer>
{({ dialog }) => dialog && <Backdrop>{dialog}</Backdrop>}
</layoutContext.Consumer>
);
export const withLayout = (WrappedComponent) => {
const WithLayout = (props) => (
<layoutContext.Consumer>
{({ dialog, setDialog }) => {
const openDialog = () => {
console.log("openDialog")
setDialog(<Dialog>hihi</Dialog>);
};
const closeDialog = () => {
setDialog(null);
};
const enhancedProps = {
openDialog,
closeDialog,
};
return (
<WrappedComponent {...props} {...enhancedProps}></WrappedComponent>
);
}}
</layoutContext.Consumer>
);
return WithLayout;
};
withLayout을 만들어서 openDialog, closeDialog를 enhancedProps로 전달을 하였습니다.
import * as MyLayout from "../lib/MyLayout";
const Page = ({ header, children, footer, openDialog }) => (
<div className="Page">
<header>{header}</header>
<main>{children}</main>
<footer>{footer}</footer>
<MyLayout.DialogContainer />
<button onClick={openDialog}>dialog</button>
</div>
);
export default MyLayout.withLayout(Page);
Page에서 MyLayout.DialogContainer이 기본값이 null인데 button을 추가하여 고차컴포넌트에서 주입받은 openDialog를 사용하여 Dialog를 렌더링하는데 성공하였습니다.
닫기도 해보고싶어서
import * as MyLayout from "../lib/MyLayout";
const Dialog = ({ closeDialog }) => (
<div className="Dialog">
<header>header</header>
<main>main</main>
<footer>footer</footer>
<button onClick={closeDialog}>closeDialog</button>
</div>
);
export default MyLayout.withLayout(Dialog);
Dialog component에 닫기 버튼을 추가하려고 MyLayout.withLayout으로 감싸니
초기화 전에 참조하려 했다는데 이 에러 자체는 이해가 가지만 왜 지금 위 상황이 이 에러에 해당되는 상황인지 이해가 가지 않습니다...
답변 1
1
Dialog.jsx에서 MyLayout 모듈을 가져올 때 참조 오류가 발생하네요
Uncaught ReferenceError: can't access lexical declaration 'withLayout' before initialization
순환 참조 오류인데요. 각 모듈이 서로 가져오기를 할경우 발생합니다. 이 경우는
MyLayout.jsx에서 Dialog.jsx를 불러오고
Dialog.jsx에서 MyLayout.jsx를 불러옴.
이 브라우져가 모듈을 가져올 때 종단점 없이 계속 가져오기를 시도하는데, 이 때 참조 오류를 예외로 발생시키는 현상입니다.
순환 참조는 코드가 많아질수록 발견될 가능성이 많고요. 고려해서 잘 설계하는 게 중요합니다.
관련해 정리한 내용도 참고해주세요.