Невозможно реализовать сценарии инициализации Materialize-CSS с NextJS - PullRequest
0 голосов
/ 02 сентября 2018

Я использую Материализация CSS для стилизации веб-приложения, над которым я работаю. Я создаю приложение, используя NextJS с ReactJS. Я уже стилизовал панель навигации, используя классы, определенные в CSS-файле Materialize. Однако я не могу реализовать функциональность адаптивной боковой панели с помощью предписанного сценария инициализации , как указано на веб-сайте Materialise .

Мой компонент Navbar (./components/Navbar.js) выглядит следующим образом:

import React, { Component, Fragment } from 'react';
import Link from 'next/link';
import $ from 'jquery';

class Navbar extends Component {
  constructor(props) {
    super(props)
    this.props = props;
  }

  componentDidMount = () => {
    document.addEventListener('DOMContentLoaded', function() {
      var elems = document.querySelectorAll('.sidenav');
      var instances = M.Sidenav.init(elems, options);
    });
  }

  render() {
    return (

      <Fragment>
        <nav>
          <div className="nav-wrapper blue">
            <Link prefetch href='/'>
              <a href="/" className="brand-logo">Project Coco</a>
            </Link>
            <a href="#" data-target="slide-out" className="sidenav-trigger"><i className="material-icons">menu</i></a>
            <ul id="nav-mobile" className="right hide-on-med-and-down">
              <li>
                <Link prefetch href='/'>
                  <a>Home</a>
                </Link>
              </li>
              <li>
                <Link prefetch href='/about'>
                  <a>About</a>
                </Link>
              </li>
              <li>
              </li>
            </ul>
          </div>
        </nav>
        {/* Sidenav markup */}
        <ul className="sidenav" id="slide-out">
          <li>
            <Link prefetch href='/'>
              <a>Home</a>
            </Link>
          </li>
          <li>
            <Link prefetch href='/about'>
              <a>About</a>
            </Link>
          </li>
        </ul>
      </Fragment>
    );
  }
}

export default Navbar;

Как очевидно, эта функциональность (боковая панель) нуждается в JQuery. Так что я уже добавил его через yarn и вызываю его, используя import $ from 'jquery'. Но после запуска выдает ошибку, говорящую, что sidenav не является функцией .

Я даже попытался полностью покончить с JQuery и просто перейти на ванильную версию сценария инициализации JS в componentDidMount:

document.addEventListener('DOMContentLoaded', function() {
    var elems = document.querySelectorAll('.sidenav');
    var instances = M.Sidenav.init(elems, options);
  });

Но на этот раз, хотя и без ошибок, функциональность все равно отказывается работать, и нажатие на меню гамбургера не вызывает sidenav, что и должно быть.

Весь репозиторий на Github для справки, а приложение-прототип доступно на schandillia.com . Какие-нибудь решения?

P.S .: Кажется, проблема в том, что код инициализации в ComponentDidMount выполняется перед MaterializeCSS.js (вызывается как внешний файл), от которого он зависит. Любой обходной путь может быть потенциальным решением, хотя это всего лишь предположение.

1 Ответ

0 голосов
/ 06 сентября 2018

Вам необходимо импортировать materialize-css в ваш компонент. К сожалению, если вы попытаетесь сделать import 'materialize-css', вы получите ошибку window is undefined. Это потому, что Next.js универсален, что означает, что он выполняет код сначала на стороне сервера, где window не существует . Обходной путь, который я использовал для этой проблемы, следующий:

Установите materialize-css, если у вас нет:

$ npm i materialize-css

Импортировать materialize-css в ваш компонент , только если определено window :

if (typeof window !== 'undefined') {
    window.$ = $;
    window.jQuery = $;
    require('materialize-css');
}

Тогда, в вашем componentDidMount методе:

componentDidMount = () => {
    $('.sidenav').sidenav();
}

Итак, ваш компонент выглядит так:

import React, { Component, Fragment } from 'react';
import Link from 'next/link';
import $ from 'jquery';

if (typeof window !== 'undefined') {
    window.$ = $;
    window.jQuery = $;
    require('materialize-css');
}

class Navbar extends Component {
    constructor(props) {
        super(props)
        this.props = props;
    }

    componentDidMount = () => {
        $('.sidenav').sidenav();
    }

    render() {
        return (
              <Fragment>
                <nav>
                    ...
                </nav>
                {/* Sidenav markup */}
                <ul className="sidenav" id="slide-out">
                    ...
                </ul>
              </Fragment>
        );
    }
}

export default Navbar;

Источники: Вопросы и ответы по Next.js и эта проблема .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...