전환이 포함된 리액트모달(에 추가)을 작성하려면 어떻게 해야 합니까?
이 답변에는 https://stackoverflow.com/a/26789089/883571에 리액트 기반 모달(모달)을 추가함으로써 작성되는 모달(모달)이 있습니다.<body>
하지만 React에서 제공하는 트랜지션 애드온과 호환되지 않습니다.
(진입 및 퇴출 중) 전환으로 작성하려면 어떻게 해야 합니까?
Ryan Florence는 react conf 2015에서 포털을 사용하는 것을 시연했습니다.다음은 심플을 작성하는 방법입니다.Portal
컴포넌트...
var Portal = React.createClass({
render: () => null,
portalElement: null,
componentDidMount() {
var p = this.props.portalId && document.getElementById(this.props.portalId);
if (!p) {
var p = document.createElement('div');
p.id = this.props.portalId;
document.body.appendChild(p);
}
this.portalElement = p;
this.componentDidUpdate();
},
componentWillUnmount() {
document.body.removeChild(this.portalElement);
},
componentDidUpdate() {
React.render(<div {...this.props}>{this.props.children}</div>, this.portalElement);
}
});
리액트에서 보통 할 수 있는 건 포털 안에서 할 수 있는 건 다...
<Portal className="DialogGroup">
<ReactCSSTransitionGroup transitionName="Dialog-anim">
{ activeDialog === 1 &&
<div key="0" className="Dialog">
This is an animated dialog
</div> }
</ReactCSSTransitionGroup>
</Portal>
jsbin demo
라이언의 리액션 모델도 보실 수 있지만, 실제로 사용해 본 적이 없기 때문에 애니메이션과 잘 어울리는지 모르겠습니다.
도움이 될 만한 모듈 반응 포털을 작성했습니다.
사용방법:
import { Portal } from 'react-portal';
<Portal>
This text is portaled at the end of document.body!
</Portal>
<Portal node={document && document.getElementById('san-francisco')}>
This text is portaled into San Francisco!
</Portal>
반응 15.x
이 문서에서 설명하는 ES6 버전의 방법은 다음과 같습니다.
import React from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
export default class BodyEnd extends React.PureComponent {
static propTypes = {
children: PropTypes.node,
};
componentDidMount() {
this._popup = document.createElement('div');
document.body.appendChild(this._popup);
this._render();
}
componentDidUpdate() {
this._render();
}
componentWillUnmount() {
ReactDOM.unmountComponentAtNode(this._popup);
document.body.removeChild(this._popup);
}
_render() {
ReactDOM.render(this.props.children, this._popup);
}
render() {
return null;
}
}
DOM 의 마지막에 배치하고 싶은 요소를, 다음과 같이 정리합니다.
<BodyEnd><Tooltip pos={{x,y}}>{content}</Tooltip></BodyEnd>
리액트 16.x
다음은 React 16의 최신 버전입니다.
import React from 'react';
import ReactDOM from 'react-dom';
export default class BodyEnd extends React.Component {
constructor(props) {
super(props);
this.el = document.createElement('div');
this.el.style.display = 'contents';
// The <div> is a necessary container for our
// content, but it should not affect our layout.
// Only works in some browsers, but generally
// doesn't matter since this is at
// the end anyway. Feel free to delete this line.
}
componentDidMount() {
document.body.appendChild(this.el);
}
componentWillUnmount() {
document.body.removeChild(this.el);
}
render() {
return ReactDOM.createPortal(
this.props.children,
this.el,
);
}
}
다른 답변에서 설명한 바와 같이 이 작업은 포털을 사용하여 수행할 수 있습니다.시작점v16.0
포털은 React에 포함되어 있습니다.
<body>
<div id="root"></div>
<div id="portal"></div>
</body>
보통 컴포넌트의 렌더 메서드에서 요소를 반환하면 가장 가까운 부모 노드의 자녀로 DOM에 마운트되지만 포털에서는 하위 요소를 DOM의 다른 위치에 삽입할 수 있습니다.
const PortalComponent = ({ children, onClose }) => {
return createPortal(
<div className="modal" style={modalStyle} onClick={onClose}>
{children}
</div>,
// get outer DOM element
document.getElementById("portal")
);
};
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
modalOpen: false
};
}
render() {
return (
<div style={styles}>
<Hello name="CodeSandbox" />
<h2>Start editing to see some magic happen {"\u2728"}</h2>
<button onClick={() => this.setState({ modalOpen: true })}>
Open modal
</button>
{this.state.modalOpen && (
<PortalComponent onClose={() => this.setState({ modalOpen: false })}>
<h1>This is modal content</h1>
</PortalComponent>
)}
</div>
);
}
}
render(<App />, document.getElementById("root"));
여기서 작업 예를 확인하십시오.
이 코드는 거의 자기 설명이며, 대부분의 사람들이 찾고 있는 핵심 솔루션을 망라하고 있습니다.
ReactDOM.render(
<Modal />,
document.body.appendChild( document.createElement( 'div' ) ),
)
여기서 근본적인 문제는 React에서는 부모에게만 컴포넌트를 마운트할 수 있다는 것입니다.이것은 항상 바람직한 동작은 아닙니다.하지만 이 문제에 어떻게 대처해야 할까요?
저는 이 문제를 해결하기 위해 해결책을 만들었습니다.자세한 문제의 정의, src 및 예는 https://github.com/fckt/react-layer-stack#rationale 에서 확인할 수 있습니다.
근거
react
/react-dom
에는, 다음의 2개의 기본적인 전제 조건/조건이 있습니다.
- 모든 UI는 자연스럽게 계층화됩니다.이 때문에 우리는
components
서로 감싸고 있다react-dom
기본적으로 하위 구성 요소를 상위 DOM 노드에 마운트(물리적으로)문제는 두 번째 자산이 경우에 따라서는 당신이 원하는 것이 아닐 수 있다는 것입니다.경우에 따라 구성 요소를 다른 물리적 DOM 노드에 마운트하고 상위 노드와 하위 노드 간의 논리적 연결을 동시에 유지할 수 있습니다.
인 예는 과 같은 컴포넌트입니다.에서는, 「Tooltip」의할 필요가 경우가 있습니다.개발 프로세스의 어느 시점에서 이 컴포넌트에 대한 설명을 추가해야 할 수 있습니다.
UI element
, 좌표를 ).UI element
코디네이트 또는 마우스 좌표)와 동시에 정보가 필요합니다.정보가 지금 당장 표시되어야 하는지 여부, 콘텐츠 및 상위 컴포넌트의 컨텍스트가 필요합니다.이 예에서는 논리 계층이 물리적 DOM 계층과 일치하지 않을 수 있습니다.
질문에 대한 답변의 구체적인 예를 보려면 https://github.com/fckt/react-layer-stack/blob/master/README.md#real-world-usage-example을 참조하십시오.
import { Layer, LayerContext } from 'react-layer-stack'
// ... for each `object` in array of `objects`
const modalId = 'DeleteObjectConfirmation' + objects[rowIndex].id
return (
<Cell {...props}>
// the layer definition. The content will show up in the LayerStackMountPoint when `show(modalId)` be fired in LayerContext
<Layer use={[objects[rowIndex], rowIndex]} id={modalId}> {({
hideMe, // alias for `hide(modalId)`
index } // useful to know to set zIndex, for example
, e) => // access to the arguments (click event data in this example)
<Modal onClick={ hideMe } zIndex={(index + 1) * 1000}>
<ConfirmationDialog
title={ 'Delete' }
message={ "You're about to delete to " + '"' + objects[rowIndex].name + '"' }
confirmButton={ <Button type="primary">DELETE</Button> }
onConfirm={ this.handleDeleteObject.bind(this, objects[rowIndex].name, hideMe) } // hide after confirmation
close={ hideMe } />
</Modal> }
</Layer>
// this is the toggle for Layer with `id === modalId` can be defined everywhere in the components tree
<LayerContext id={ modalId }> {({showMe}) => // showMe is alias for `show(modalId)`
<div style={styles.iconOverlay} onClick={ (e) => showMe(e) }> // additional arguments can be passed (like event)
<Icon type="trash" />
</div> }
</LayerContext>
</Cell>)
// ...
나는 이것을 돕기 위해 도서관을 썼다.포털 전략에서 사용되는 DOM 삽입 해킹을 피하고 컨텍스트 기반 레지스트리를 사용하여 소스에서 타깃으로 컴포넌트를 전달합니다.
구현에서는 표준 React 렌더 사이클을 사용합니다.텔레포트/인젝트/트랜스포트하는 컴포넌트는 타겟에 이중 렌더 사이클을 발생시키지 않습니다.모든 것이 동시에 발생합니다.
API는 소스/타겟을 정의하기 위해 코드에서 마법 문자열을 사용하지 않도록 구성되었습니다.대신 대상(Injectionable) 및 원본(Injectionor)으로 사용할 구성요소를 명시적으로 작성하고 장식해야 합니다.이러한 종류의 일은 일반적으로 매우 마술적인 것으로 간주되기 때문에, 컴포넌트의 명시적인 표현(직접 Import 및 사용 필요)은 컴포넌트가 삽입되는 장소에 대한 혼란을 완화하는 데 도움이 될 수 있다고 생각합니다.
내 라이브러리에서 문서의 직계 하위 항목으로 렌더링할 수 없습니다.본문 구성 요소 트리의 루트 수준 구성 요소에 바인딩하여 허용 가능한 모달 효과를 얻을 수 있습니다.조만간 이 사용 사례의 예를 추가할 예정입니다.
상세한 것에 대하여는, https://github.com/ctrlplusb/react-injectables 를 참조해 주세요.
도움이 됐으면 좋겠다.위의 anwser에 근거한 이행모달의 현재 실장입니다.
React = require 'react/addons'
keyboard = require '../util/keyboard'
mixinLayered = require '../mixin/layered'
$ = React.DOM
T = React.PropTypes
cx = React.addons.classSet
module.exports = React.createFactory React.createClass
displayName: 'body-modal'
mixins: [mixinLayered]
propTypes:
# this components accepts children
name: T.string.isRequired
title: T.string
onCloseClick: T.func.isRequired
showCornerClose: T.bool
show: T.bool.isRequired
componentDidMount: ->
window.addEventListener 'keydown', @onWindowKeydown
componentWillUnmount: ->
window.removeEventListener 'keydown', @onWindowKeydown
onWindowKeydown: (event) ->
if event.keyCode is keyboard.esc
@onCloseClick()
onCloseClick: ->
@props.onCloseClick()
onBackdropClick: (event) ->
unless @props.showCornerClose
if event.target is event.currentTarget
@onCloseClick()
renderLayer: ->
className = "body-modal is-for-#{@props.name}"
$.div className: className, onClick: @onBackdropClick,
if @props.showCornerClose
$.a className: 'icon icon-remove', onClick: @onCloseClick
$.div className: 'box',
if @props.title?
$.div className: 'title',
$.span className: 'name', @props.title
$.span className: 'icon icon-remove', @onCloseClick
@props.children
render: ->
$.div()
언급URL : https://stackoverflow.com/questions/28802179/how-to-create-a-react-modal-which-is-appended-to-body-with-transitions
'sourcetip' 카테고리의 다른 글
오라클 데이터베이스에서 무작위로 레코드를 가져오려면 어떻게 해야 합니까? (0) | 2023.03.09 |
---|---|
React Functional Components의 모든 함수 핸들러에서 Callback을 사용해야 합니까? (0) | 2023.03.09 |
WordPress 다중 사이트 설정에서 다른 사이트의 게시물을 표시하려면 어떻게 해야 합니까? (0) | 2023.03.09 |
HTML 양식을 제출하지 않도록 합니다. (0) | 2023.03.09 |
에서 .에서 .에서 . (0) | 2023.03.09 |