我使用React和firebase创建简化的松弛并使用MDl作为样式。我试图集成一个按钮,打开一个对话框来获取一些用户输入,在这种情况下是新聊天室的名称,然后在提交时它会将数据发送到firebase并将其存储在房间中数组并在列表中显示新的房间名称。我已经设置了表单以获取用户输入,然后我尝试重构它以在对话框中工作,我似乎停留在如何让对话框工作。这是我的整个组成部分:
import React, { Component } from 'react';
import './RoomList.css';
import dialogPolyfill from 'dialog-polyfill';
class RoomList extends Component {
constructor(props) {
super(props);
this.state = { rooms: [] };
this.roomsRef = this.props.firebase.database().ref('rooms');
this.handleChange = this.handleChange.bind(this);
this.createRoom = this.createRoom.bind(this);
}
handleChange(e){
this.setState({ name: e.target.value });
}
createRoom(e) {
e.preventDefault();
this.roomsRef.push({ name: this.state.name });
this.setState({ name: "" });
}
componentDidMount() {
this.roomsRef.on('child_added', snapshot => {
const room = snapshot.val();
room.key = snapshot.key;
this.setState({ rooms: this.state.rooms.concat( room ) });
})
}
dialogBox(e){
const dialogButton = document.getElementsByClassName('dialog-
button');
const dialog = document.getElementById('dialog');
if (! dialog.showModal) {
dialogPolyfill.registerDialog(dialog);
}
dialogButton.onClick( (e) => {
dialog.showModal();
});
dialog.document.getElementsByClassName('submit-close').onCLick(
(e) => {
dialog.close();
});
}
render() {
const roomlist = this.state.rooms.map( (room) =>
<span className="mdl-navigation__link" key={room.key}>
{room.name}</span>
);
const newListForm = (
<div id="form">
<button className="mdl-button mdl-js-button mdl-button--
raised mdl-js-ripple-effect dialog-button">Add room</button>
<dialog id="dialog" className="mdl-dialog">
<h3 className="mdl-dialog__title">Create Room name</h3>
<div className="mdl-dialog__content">
<p>Enter a room name</p>
</div>
<div className="mdl-dialog__actions">
<form onSubmit={this.createRoom}>
<div className="mdl-textfield mdl-js-textfield">
<input type="text" value={this.state.name}
className="mdl-textfield__input" id="rooms" onChange=
{this.handleChange} />
<label className="mdl-textfield__label"
htmlFor="rooms">Enter room Name...</label>
<button type="submit" className="mdl-button submit-
close">Submit</button>
<button type="button" className="mdl-button submit-
close">Close</button>
</div>
</form>
</div>
</dialog>
</div>
);
return (
<div className="layout mdl-layout mdl-js-layout mdl-layout--
fixed-drawer mdl-layout--fixed-header">
<header className="header mdl-layout__header mdl-color--
grey-100 mdl-color-text--grey-600">
<div className="mdl-layout__header-row">
<span className="mdl-layout-title">Bloc Chat</span>
<div className="mdl-layout-spacer"></div>
</div>
</header>
<div className="drawer mdl-layout__drawer mdl-color--blue-
grey-900 mdl-color-text--blue-grey-50">
<header className="drawer-header">
<span>{newListForm}</span>
</header>
<nav className="navigation mdl-navigation mdl-color--
blue-grey-800">
<div>{roomlist}</div>
<div className="mdl-layout-spacer"></div>
</nav>
</div>
</div>
);
}
}
export default RoomList;
答案 0 :(得分:0)
以下是有关如何使用simple portal
可以找到工作演示here。只需使用下拉菜单导航到import React, { Component } from "react";
import { createPortal } from "react-dom";
import "./simple-portal.css";
export default class SimplePortal extends Component {
constructor() {
super();
this.state = {
list: [],
input: "",
showDialog: false
};
this._onChange = this._onChange.bind(this);
this._onSubmit = this._onSubmit.bind(this);
}
_onChange(e) {
let input = e.target.value;
this.setState({ input });
}
_onSubmit(e) {
e.preventDefault();
let showDialog = false;
// Dont Mutate the State!!!
let list = this.state.list.slice();
list.push(this.state.input);
this.setState({ showDialog, list, input: "" });
}
render() {
const { showDialog, list, input } = this.state;
return (
<div className="container">
<div>
<button
className="btn"
onClick={e =>
this.setState({
showDialog: !showDialog
})
}
>
Add Item
</button>
</div>
{/* Render Items from List */}
<div>
<ul>
{list.map(item => {
return <li key={item}>{item}</li>;
})}
</ul>
</div>
{/* Show Modal - Renders Outside React Hierarchy Tree via Portal Pattern */}
{showDialog === true ? (
<DialogModal>
<div className="dialog-wrapper">
<h1>New List Item</h1>
<form onSubmit={this._onSubmit}>
<input type="text" value={input} onChange={this._onChange} />
</form>
</div>
</DialogModal>
) : null}
</div>
);
}
}
class DialogModal extends Component {
constructor() {
super();
this.body = document.getElementsByTagName("body")[0];
this.el = document.createElement("div");
this.el.id = "dialog-root";
}
componentDidMount() {
this.body.appendChild(this.el);
}
componentWillUnmount() {
this.body.removeChild(this.el);
}
render() {
return createPortal(this.props.children, this.el);
}
}
演示。可以在github上找到完整代码库的快照。
const Data = require('./Models/Data');
...
let example = new Data( sample );
example.save( function ( err ){
console.log('test);
if ( err ) {
console.log('Error saving Data. 'Error: ', err);
}
});
答案 1 :(得分:0)
我没有在你的按钮上看到任何会触发模态渲染的事件监听器。我会通过指定一个onClick事件来处理这个问题,该事件将更新将呈现模态/对话框的状态。
另一种解决方案,可能是您的想法,就是让状态发生变化,以便在createRoom()函数中呈现模态/对话框。请记住,更新状态或获取新道具将触发组件的渲染。您正在尝试更新状态以重新渲染组件,并显示模式/对话框。
很抱歉,如果我误解了这个问题或你的目标。