React.js Обработка серверов и обработчики событий

Я изучаю использование response.js и имею некоторые проблемы для использования обработчиков событий. Последний вопрос: возможно ли использовать рендеринг на стороне сервера и отправлять обработчики событий клиенту автоматически?

Вот мой пример: У меня есть index.jsx, который я обрабатываю на стороне сервера и отправляю клиенту

var React = require("react");
var DefaultLayout = require("./layout/default");

var LikeButton = React.createClass({
  getInitialState: function() {
    return {liked: false}; 
  }, 
  handleClick: function(event) {
    this.setState({liked: !this.state.liked});
  }, 
  render: function() {
    var text = this.state.liked ? 'like' : 'haven\'t liked';
    return (
      <p onClick={this.handleClick}>
        You {text} this. Click to toggle.
      </p>
    );
  } 
});

var IndexComponent = React.createClass({
   render: function(){
       return (
           <DefaultLayout title={this.props.name}>
                <div>
                        <h1>React Test</h1>
                </div>

                <div id="testButton">
                    <LikeButton/>
                </div> 

                <script type="text/babel" src="/js/react.js"></script>
           </DefaultLayout>
       )
   }   
});

Но у "Like Button" нет никакого взаимодействия. Чтобы заставить его делать что-то по клику, я должен добавить эту клиентскую сторону кода.

var LikeButton = React.createClass({
  getInitialState: function() {
    return {liked: false};
  },
  handleClick: function(event) {
    this.setState({liked: !this.state.liked});
  },
  render: function() {
    var text = this.state.liked ? 'like' : 'haven\'t liked';
    return (
      <p onClick={this.handleClick}>
        You {text} this. Click to toggle.
      </p>
    );
  }
});

ReactDOM.render(
  <LikeButton />,
  document.getElementById('testButton')
);

Я только начинал с react.js, и, возможно, я просто пропустил некоторые основные концепции здесь. Но почему response.js не просто создает код (который я теперь должен добавить вручную клиенту) при рендеринге сервера страниц? Таким образом, у меня избыточный код, и похоже, что это будет беспорядок в больших приложениях. По крайней мере, response.js достаточно умен, чтобы не рисовать два LikeButtons, а "привязать" одну созданную сторону сервера к компоненту на стороне клиента.

Ответ 1

Для интерактивного приложения React для клиентской стороны вам необходимо также отобразить клиентскую сторону приложения. Обычно этот код идентичен коду, который вы запускаете на сервере, поэтому нет избыточного кода. Это тот же код. Вы можете спросить себя, может ли рендеринг как на клиенте, так и на сервере быть переполненным, но с точки зрения производительности и SEO это имеет смысл.

ReactDOMServer.renderToString(<MyApp foo={bar} />) в основном просто выводит строку с разметкой. В нем нет javascript или какой-либо магии. Просто простой старый HTML. Тем не менее, в рендеринговой разметке есть много атрибутов React ID, которые позже используются на клиенте для генерации начальных виртуальных DOM и прикрепленных событий.

При повторной визуализации вашего приложения на клиенте на том же элементе DOM, в котором ваша разметка на стороне сервера была отображена на сервере, React не требует перерисовки всего приложения. Он просто создает новое виртуальное дерево DOM, отличает его от исходного дерева виртуальной DOM и выполняет необходимые операции DOM, если таковые имеются. Эта концепция виртуального DOM - это то, что заставляет React так быстро в первую очередь. В том же процессе любые прослушиватели событий, которые вы определили в своем приложении, будут прикреплены к уже сделанной разметке.

Все это происходит очень быстро. И у вас есть преимущество страницы с предоставленной на стороне сервера (которая может быть кэширована на сервере, используя Varnish или что-то подобное), что поисковые системы будут обходить, пользователям не нужно ждать чего-либо, чтобы увидеть первоначальный рендер, а страница в основном работает для пользователей, которые отключили javascript.

Ответ 2

Это поведение объясняется тем, что именно является рендерингом на стороне сервера. Во-первых, вам придется запускать тот же код как на стороне клиента, так и на стороне сервера. Это то, что называется изоморфным приложением. Один, который запускается как на сервере, так и на клиенте.
Таким образом, при выполнении ReactDOM.renderToString(<Component>) только HTML отображается как строка. Метод рендеринга вашего компонента оценивается и генерируется HTML, необходимый для первоначального рендеринга.
Когда один и тот же код запускается на клиенте, реакция просматривает HTML-рендеринг и прикрепляет JS в необходимых местах. Реакт умен таким образом, он не повторяет все снова на стороне клиента. Просто оценивает код и определяет, где все для присоединения кода, основанного на react-id, указывается каждый элемент DOM. (Вы будете реагировать-id, если вы проверите элемент любого реагирующего приложения)

Теперь можно спросить, в чем преимущество повторения одной и той же вещи дважды?
и пользователь отвечает perceived loading time. А также некоторый минимальный просмотр для пользователей, которые отключили JS.

Клиентское приложение
Так работает только клиентское приложение. (клиент также получил приложение React)

клиентское приложение</a

Пользователь будет видеть контент только после скелета HTML, JS-пакетов (которые часто довольно большие), и данные извлекаются и оцениваются. Это означает, что пользователю часто приходится некоторое время смотреть на счетчик или экран загрузки, пока все не загрузится.

Изоморфное приложение (выполняется как на клиенте, так и на сервере)
Как работает изоморфное приложение,
серверное приложение
В этом случае сервер генерирует HTML полный, оценивая ваш компонент. Пользователь сразу же увидит контент сразу после загрузки HTML-кода. Хотя приложение будет работать только после того, как пакеты JS также будут загружены и оценены. Таким образом, JS должен работать с обеих сторон
Таким образом, пользователь видит контент намного быстрее, чем раньше. Следовательно, огромное снижение воспринимаемого времени загрузки.