blog-app
api
db.json
client
public
index.html
modal.html
src
actions
index.js
types.js
apis
streams.js
components
StreamCreate.js
StreamDelete.js
StreamEdit.js
StreamForm.js
StreamList.js
App.js
GoogleAuth.js
Header.js
Modal.js
reducers
authReducer.js
index.js
streamReducer.js
history.js
index.js
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<div id="modal"></div>
...
<head>
<style>
.sidebar {
position: fixed;
top: 0;
left: 0;
height: 100vh;
width: 300px;
background-color: green;
}
.content {
margin-left: 300px;
}
.modal-body {
background-color: white;
margin: auto;
height: 30%;
width: 30%;
}
.modal {
height: 100%;
width: 100%;
position: fixed;
background-color: grey;
left: 0;
top: 0;
z-index: 10;
}
.positioned {
position: relative;
z-index: 0;
}
</style>
</head>
<body>
<div class="modal">
<div class="modal-body"><h1>I am a modal</h1></div>
</div>
<div class="positioned">alskjdflk asldkfjalskdjf asldfkjalskdf</div>
<div class="sidebar">I am a sidebar</div>
<div class="content"><h1>I am some content</h1></div>
</body>
import React from "react";
import ReactDOM from "react-dom";
import history from '../history';
const Modal = props => {
return ReactDOM.createPortal(
<div onClick={props.onDismiss} className="ui dimmer modals visible active">
<div
onClick={e => e.stopPropagation()}
className="ui standard modal visible active"
>
<div className="header">{props.title}</div>
<div className="content">{props.content}</div>
<div className="actions">{props.actions}</div>
</div>
</div>,
document.querySelector('#modal')
);
};
export default Modal;
ReactDOM.createPortal
Portals 는 리액트 프로젝트에서 컴포넌트를 렌더링하게 될 때,
UI 를 어디에 렌더링 시킬지 DOM 을 사전에 선택하여
부모 컴포넌트의 바깥에 렌더링 할 수 있게 해주는 기능입니다.
이 기능은 리액트 v16 에서 도입된 기능인데요, 기존의 리액트에서 컴포넌트를 렌더링 하게 될 때,
children 은 부모컴포넌트의 DOM 내부에 렌더링 되어야 했었습니다
const Wrapper = ({ children }) => {
return <div>{children}</div>;
}
Portals 를 사용하면 DOM 의 계층구조 시스템에 종속되지 않으면서 컴포넌트를 렌더링 할 수 있습니다.
const MyPortal = ({ children }) => {
const el = document.getElementById('my-portal');
return ReactDOM.createPortal(children, el);
}
참고:https://velog.io/@velopert/react-portals
4.src/components/StreamDelete.js
import React from "react";
import { connect } from "react-redux";
import { Link } from "react-router-dom";
import Modal from "../Modal";
import history from "../../history";
import { fetchStream, deleteStream } from "../../actions";
class StreamDelete extends React.Component {
componentDidMount() {
this.props.fetchStream(this.props.match.params.id);
}
renderActions() {
const { id } = this.props.match.params;
return (
<React.Fragment>
<button
onClick={() => this.props.deleteStream(id)}
className="ui button negative"
>
Delete
</button>
<Link to="/" className="ui button">
Cancel
</Link>
</React.Fragment>
);
}
renderContent() {
if (!this.props.stream) {
return "Are you sure you want to delete this stream?";
}
return `Are you sure you want to delete the stream with title: ${this.props.stream.title}`;
}
render() {
return (
<div>
StreamDelete
<Modal
title="Delete Stream"
content={this.renderContent()}
actions={this.renderActions()}
onDismiss={() => history.push("/")}
/>
</div>
);
}
}
const mapStateToProps = (state, ownProps) => {
return { stream: state.streams[ownProps.match.params.id] };
};
export default connect(mapStateToProps, { fetchStream, deleteStream })(
StreamDelete
);
Fragment
React의 패턴은 Component가 여러 요소를 반환하는 것이 일반적입니다.
Fragements 를 사용하면 DOM 노드에 추가하지 않고 하위의 목록을 그룹화 할 수 있습니다.
참고:https://a-tothe-z.tistory.com/26
BlogApp7 StreamShow (0) | 2020.08.21 |
---|---|
Blog App3 StreamList (0) | 2020.08.20 |
React Router를 이용하여 component간에 props 넘겨주기 (0) | 2020.08.20 |
Blog App5 StreamEdit (0) | 2020.08.20 |
redux-form (0) | 2020.08.20 |