Как перезагрузить ReactJS Компонент в ванили HTML / JS? - PullRequest
1 голос
/ 06 апреля 2020

Это может быть глупый вопрос. Но по сути я создаю компонент React Modal, который можно использовать в любых vanilla HTML / JS файлах. Я могу создать файл комплекта. js из моего компонента React с помощью Webpack, который затем может быть вставлен в тег div файла Vanilla HTML следующим образом:

<div id="my-modal-target"></div>
<script src="bundle.js"></script>

Поскольку я Я пытаюсь создать модальный режим, и каждый раз, когда пользователь нажимает кнопку «Выход», мой компонент React условно отображает модальный режим, который будет скрыт. Однако я пытаюсь выяснить, как повторно загрузить компонент React, нажав кнопку в целевом файле Vanilla HTML. Буду признателен за любые предложения о том, как мне поступить. Вот некоторые вещи, которые я попробовал:

  • , используя "ReactDOM.unmountComponentAtNode (document.getElementById (DIV_TAG_NAME));" принудительно размонтировать компонент React из тега div в целевом объекте HTML, а затем повторно загрузить тег div с помощью JQuery. Однако, это, кажется, вызывает проблему CORS, которая не позволяет мне повторно загрузить тег div. Кроме того, это просто не похоже на хорошую практику на стороне React.
  • при нажатии кнопки в файле Vanilla HTML, он переходит в подпорку в компонент React. Однако, похоже, это не работает, поскольку реквизиты передаются только при первой загрузке компонента React. Другими словами, если изменить реквизиты в файле Vanilla HTML, это не повлияет на компонент React.

Заранее большое спасибо за любую помощь!

1 Ответ

1 голос
/ 06 апреля 2020

Существует несколько способов, которыми вы можете выполнить sh Реактивная / нереактивная связь.

Использование пользовательских событий

Хотя у каждого метода есть свои плюсы и минусы, этот является преимуществом. Быть рамочной агностией c. Вы можете сделать то же самое для компонента Vue и ванили js. Недостатком является то, что вам нужно найти способ управлять и документировать события в чистом виде, иначе ваше приложение может быстро стать недоступным.


Внутри вашего компонента вам нужно создавать и прослушивать собственные событие. Затем вы можете отправить его из любого места, и компонент будет перехватывать его и обновлять соответствующим образом.

const OPEN_EVENT_NAME = 'open';
const CLOSE_EVENT_NAME = 'close';

const container = document.querySelector('#app');

class App extends React.Component {
  constructor(props) {
    super(props);
 
    this.state = {
      open: true,
    }
    
    // Bind the "open" and "close" events to their respective functions
    container.addEventListener(OPEN_EVENT_NAME, this.openModal);
    container.addEventListener(CLOSE_EVENT_NAME, this.closeModal);
  }
  
  openModal = () => {
    this.setState({ open: true });
  }
  
  closeModal = () => {
    this.setState({ open: false });
  }

  render() {
    return (
      <div>The modal is {this.state.open ? 'open' : 'closed'}</div>
    )
  };
}

ReactDOM.render(<App />, container);

// Create custom events
const openEvent = new Event(OPEN_EVENT_NAME);
const closeEvent = new Event(CLOSE_EVENT_NAME);

// Create events dispatchers
const openModal = () => container.dispatchEvent(openEvent);
const closeModal = () => container.dispatchEvent(closeEvent);

// Dispatch events on buttons click
document.querySelector('#open-btn').addEventListener('click', openModal);
document.querySelector('#close-btn').addEventListener('click', closeModal);
body {
  font-family: 'system-ui';
  padding: 12px;
}

h2 {
  font-weight: bold;
  margin: 0;
  margin-bottom: 6px;
}

hr {
  margin: 12px 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

<h2>
This is React
</h2>
<div id="app"></div>

<hr>

<h2>
This is not React
</h2>

<button id="open-btn">
Open modal
</button>

<button id="close-btn">
Close modal
</button>

Использование ссылок

Ссылки обычно используются для доступа к базовому элементу DOM компонента React.

Они также могут быть использованы для присоединения компонента к объекту окна, таким образом получая доступ к его состоянию и предоставляя доступ к его методам.

Этот метод менее подвержен ошибкам, поскольку вы говорите на том же языке, что и ваш компонент (состояние, методы и т. Д.). c.) Но это также недостаток, потому что это подразумевает, что конечный пользователь вашего компонента имеет некоторое знакомство с React, а это может быть и не так.


Вот как это сделать. благодаря этой статье .

class App extends React.Component {
  constructor(props) {
    super(props);
 
    this.state = {
      open: true,
    }
  }
  
  openModal = () => {
    this.setState({ open: true });
  }
  
  closeModal = () => {
    this.setState({ open: false });
  }

  render() {
    return (
      <div>The modal is {this.state.open ? 'open' : 'closed'}</div>
    )
  };
}

ReactDOM.render(<App ref={myComponent => window.myComponent = myComponent} />, document.querySelector('#app'));
body {
  font-family: 'system-ui';
  padding: 12px;
}

h2 {
  font-weight: bold;
  margin: 0;
  margin-bottom: 6px;
}

hr {
  margin: 12px 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

<h2>
This is React
</h2>
<div id="app"></div>

<hr>

<h2>
This is not React
</h2>

<button onclick="window.myComponent.openModal()">
Open modal
</button>

<button onclick="window.myComponent.closeModal()">
Close modal
</button>

- Обновление -

Поскольку вы используете перехватчики React и не можете ссылаться на функциональный компонент, я я бы не советовал использовать подход № 2.

Я создал мини-пример того, как я реализую подход № 1 (используя события для взаимодействия с React).

Как указано выше, это обеспечивает гораздо приятнее API для конечных пользователей и может быть самым чистым решением из этих двух.

Это демо доступно здесь.

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