Недопустимый реквизит «открыть» типа «функция», предоставленный в `Диалог`

#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 раза.