#javascript #reactjs #redux #material-ui
#javascript #reactjs #redux #материал-пользовательский интерфейс
Вопрос:
При нажатии на значок должно появиться диалоговое окно с формой для добавления вкладки или удаления определенной вкладки. Я использовал reactjs, redux и material-ui для компонентов. Я мог бы показать диалоговое окно при нажатии на значок, но я получаю сообщение об ошибке
Недопустимый реквизит
open
типаfunction
, предоставленныйDialog
, ожидаемыйboolean
в диалоговом окне
Диалоговое окно открывается с указанной выше ошибкой, и когда я нажимаю кнопку закрытия, ничего не происходит.
Что я должен сделать, чтобы решить эту проблему?
Вот мой код
App.js
class App extends Component {
constructor(props) {
super(props);
this.state = {
max_char: 32,
open: false,
};
this.handleChange = this.handleChange.bind(this);
this.handleLogout = this.handleLogout.bind(this);
}
handleClose = () => this.setState({ open: false });
handleOpen = () => this.setState({ open: true });
render() {
return (
<div>
<Header
tab={this.state.tabs}
open={this.state.open}
handleClose={this.handleClose}
handleToggle={this.handleToggle}
/>
<Content
handleOpen={this.handleOpen}
handleClose={this.handleClose}
/>
</div>
);
}
}
Header.js
class Header extends Component {
render() {
const tabs = _.map(this.props.tab, (tab) =>
<span className="tab" key={tab.id}><a href="">{tab.description}</a></span>
);
return (
<div>
<AppBar
title={tabs}
iconElementRight={navigation}
onLeftIconButtonTouchTap={this.props.handleToggle}
style={{ background: '#fff' }}
/>
</div>
);
}
}
function mapStateToProps(state) {
return {
iconList: state.iconList
};
}
function mapDispatchToProps(dispatch) {
return bindActionCreators({
selectTabIcon
}, dispatch);
}
const Content = (props) =>
(
<div className="content-section">
<TabDialog
open={props.handleOpen}
close={props.handleClose}
/>
</div>
);
TabDialog.js
class TabDialog extends Component {
renderAddTab() {
const actions = [
<FlatButton
label="Cancel"
primary
onTouchTap={this.props.close}
/>,
<FlatButton
label="Add Tab"
primary
keyboardFocused
onTouchTap={this.props.close}
/>,
];
return (
<div className="device-action">
<Dialog
title="Add a Tab"
actions={actions}
modal={false}
open={this.props.open}
onRequestClose={this.props.close}
>
<div className="tab-name">
<TextField
floatingLabelText="Name"
floatingLabelStyle={{ color: '#1ab394' }}
floatingLabelFocusStyle={{ color: '#1db4c2' }}
underlineStyle={{ borderColor: '#1ab394' }}
/>
</Dialog>
</div>
);
}
renderDeleteTab() {
const actions = [
<FlatButton
label="Cancel"
primary
onTouchTap={this.props.close}
/>,
<FlatButton
label="Delete"
primary
keyboardFocused
onTouchTap={this.props.close}
/>,
];
return (
<div className="tab-action">
<Dialog
title="Delete"
actions={actions}
modal={false}
open={this.props.open}
onRequestClose={this.props.close} />
</div>
);
}
render() {
const iconSelected = this.props.createTab;
if (!iconSelected) {
return (<div>Select</div>);
}
if (iconSelected === '1') {
return (this.renderDeleteTab());
}
if (iconSelected === '2') {
return (this.renderAddTab());
}
}
}
function mapStateToProps(state) {
return {
iconList: state.iconList,
createTab: state.createTab,
};
}
function mapDispatchToProps(dispatch) {
return bindActionCreators({
addTab,
selectTabIcon
}, dispatch);
}
часть redux
export function selectTabIcon(selectTab) {
console.log('selected', selectTab.target.id);
return {
type: 'TAB_ICON_SELECTED',
payload: selectTab.target.id,
};
}
switch (action.type) {
case 'TAB_ICON_SELECTED':
console.log('tab', action.payload);
return action.payload;
Обновить:
Реквизит открытия диалога принимает логическое значение и onRequestClose, onTouchTap принимает функцию, поэтому я сделал следующее, но закрытие сейчас не работает
изменил мою функцию selectTabIcon как
export function selectTabIcon(selectTab) {
return {
type: 'TAB_ICON_SELECTED',
id: selectTab.target.id,
open: true,
close: () => false
};
}
и в диалоговом окне я передал this.props.createTab.close в onRequestClose и onTouchTap, но безуспешно.
Ответ №1:
open
реквизит для диалога должен быть логическим значением в соответствии с документами Material ui http://www.material-ui.com/#/components/dialog
.
Так что надеюсь, что этот фрагмент вашего кода поможет вам:
class App extends Component {
constructor(props) {
super(props);
this.state = {
max_char: 32,
};
this.handleChange = this.handleChange.bind(this);
this.handleLogout = this.handleLogout.bind(this);
}
render() {
return (
<div>
<Header tab={this.state.tabs} />
<Content />
</div>
);
}
}
class Header extends Component {
render() {
const tabs = _.map(this.props.tab, (tab) =>
<span className="tab" key={tab.id}><a href="">{tab.description}</a></span>
);
return (
<div>
<AppBar
title={tabs}
iconElementRight={navigation}
onLeftIconButtonTouchTap={this.props.handleToggle}
style={{ background: '#fff' }}
/>
</div>
);
}
}
function mapStateToProps(state) {
return {
iconList: state.iconList
};
}
function mapDispatchToProps(dispatch) {
return bindActionCreators({
selectTabIcon
}, dispatch);
}
class TabDialog extends Component {
constructor(props) {
super(props);
this.state = {
open: false
}
this.handleOpen = this.handleOpen.bind(this)
this.handleClose = this.handleClose.bind(this)
}
handleOpen = () => {
this.setState({ open: true });
}
handleClose = () => {
this.setState({ open: false });
}
renderAddTab() {
const actions = [
<FlatButton
label="Cancel"
primary
onTouchTap={this.handleClose}
/>,
<FlatButton
label="Add Tab"
primary
keyboardFocused
onTouchTap={this.handleClose}
/>,
];
return (
<div className="device-action">
<Dialog
title="Add a Tab"
actions={actions}
modal={false}
open={this.state.open}
onRequestClose={this.handleClose}
>
<div className="tab-name">
<TextField
floatingLabelText="Name"
floatingLabelStyle={{ color: '#1ab394' }}
floatingLabelFocusStyle={{ color: '#1db4c2' }}
underlineStyle={{ borderColor: '#1ab394' }}
/>
</Dialog>
</div>
);
}
renderDeleteTab() {
const actions = [
<FlatButton
label="Cancel"
primary
onTouchTap={this.handleClose}
/>,
<FlatButton
label="Delete"
primary
keyboardFocused
onTouchTap={this.handleClose}
/>,
];
return (
<div className="tab-action">
<Dialog
title="Delete"
actions={actions}
modal={false}
open={this.state.open}
onRequestClose={this.handleClose}
/>
</div>
);
}
render() {
const iconSelected = this.props.createTab;
if (!iconSelected) {
return (<div>Select</div>);
}
if (iconSelected === '1') {
return (this.renderDeleteTab());
}
if (iconSelected === '2') {
return (this.renderAddTab());
}
}
}
function mapStateToProps(state) {
return {
iconList: state.iconList,
createTab: state.createTab,
};
}
function mapDispatchToProps(dispatch) {
return bindActionCreators({
addTab,
selectTabIcon
}, dispatch);
}
Я сомневаюсь onTouchTap
, что реквизит установлен на плоской кнопке, а также нет метода connect, который соединяет хранилище redux с компонентом
Комментарии:
1. Этот способ тоже не работает. Когда я нажимаю значок добавления, this.state.open возвращает значение false. Состояние не обновляется при нажатии на значок.
2. Раздел обновления в моем вопросе работает только при открытии диалогового окна, но закрытие не работает. Хотя я предоставил функцию для закрытия.
3. При нажатии на значок добавления
this.state.open
возвращает false, поскольку в конструкторе для начального состояния установлено значение false. ИзменитеonTouchTap
обратный вызов для плоской кнопки наrenderAddTab()
handleOpen
вместоhandleClose
того, чтобы устанавливать состояние при запуске события4. Также я предлагаю вам просмотреть приведенные здесь примеры
http://www.material-ui.com/#/components/dialog
, понять их и попробовать еще раз5. Как может появиться мое диалоговое окно, когда я меняю handleClose на handleOpen в Flatbutton? Потому что сама кнопка Flatbutton находится в диалоговом окне. Я знаю, что в примере используется кнопка. При нажатии на него состояние обновляется до true, при этом появляется диалоговое окно. В моем случае при нажатии на значок и значке ==2 это означает, что если это значок добавления, должна вызываться вкладка renderAddTab, где должно быть указано значение open prop true
Ответ №2:
Реквизит «open» диалогового окна — это bool. Вам нужно передать результат вашей функции «handleOpen», а не ссылку на саму функцию. Добавьте скобки следующим образом:
<Content handleOpen={this.handleOpen()}
handleClose={this.handleClose()}
/>
Комментарии:
1. Я получаю дополнительную ошибку, и если мне понравилось, мое приложение вылетает. Предупреждение: setState (…): невозможно обновить во время существующего перехода состояния (например, внутри
render
конструктора или другого компонента). Методы рендеринга должны быть чистой функцией реквизита и состояния; побочные эффекты конструктора являются анти-шаблоном, но могут быть перемещеныcomponentWillMount
. Он выполняется 992 раза.