Реагировать на изоморфный компонент как на стороне клиента, так и на стороне сервера.
Я хочу создать реагирующее приложение как на стороне клиента, так и на стороне сервера.
Вот пример:
import styles from './Main.css';
import React, {Component} from 'react';
import Info from './Info/Info';
import Record from './Record/Record'
export default class Main extends Component {
render() {
return (
<div className={styles.main}>
<div className={styles.mainIn + ' clearfix'}>
<div className={styles.mainLeft}>
<Info info_num="2012201972"/>
</div>
<div className={styles.mainRight}>
<div className="clearfix mb20">
<Record />
</div>
</div>
</div>
</div>
)
}
}
В этом компоненте Main
, он должен быть представлен на стороне клиента, за исключением <Record />
Составная часть Record
import styles from './Record.css';
import layout from '../../shared/styles/layout.css'
import React, {Component} from 'react';
export default class Record extends Component {
render() {
return (
<div className="float_two">
<div className={layout.box + ' mr10'}>
This is Record!
</div>
<div>
)
}
}
Вот мой вопрос:
Я искал несколько примеров серверного рендеринга с ReactDom.renderToString
а также react-router
, Тем не менее, не существует учебника как на стороне клиента, так и на стороне сервера рендеринга.
Я хочу добиться того, чтобы клиент сначала загружал и рендерил компонент <Main />
а затем загружает <Record />
со стороны сервера.
Другой вопрос заключается в том, как загрузить модуль стиля Record.css с renderToString, потому что я думаю, что в этом renderToString можно просто загрузить html-вещи, а не css.
2 ответа
Когда люди ссылаются на рендеринг на стороне сервера, они обычно ссылаются на начальный рендеринг приложения верхнего уровня по определенному маршруту, а не на отдельные компоненты.
У меня возникли проблемы с пониманием того, что ваш вариант использования соответствует тому, о чем вы просили Ваше приложение React представляет собой одно большое дерево Fragments
Таким образом, рендеринг одного компонента на стороне сервера не имеет смысла. Если ты хочешь Record
чтобы быть частью React, клиенту нужно знать об этом, так почему бы просто не сделать это на стороне клиента, как обычно?
Если вам действительно нужно отобразить его на стороне сервера, то, я думаю, вы могли бы построить компонент Record так, чтобы он выполнял запрос AJAX, а затем возвращенный html мог быть обработан с использованием https://facebook.github.io/react/tips/dangerously-set-inner-html.html, но я бы не стал его рекомендовать.
Я думаю, что Record
требуются какие-то данные со стороны сервера, и поэтому вы хотите рендерить их там? Вместо этого просто извлеките эти данные как JSON и используйте их для визуализации клиентской части компонента.
Прочитав ваши комментарии, я знаю, что вы пытаетесь сделать. Вам нужно динамически загружать контент (не визуализированный html) с сервера в ответ на какое-либо событие (прокрутка, нажатие кнопки или что-то еще). Реагировать очень хорошо в этом. Изменяя состояние (то есть, какие записи есть) вашего приложения, React позаботится об эффективной визуализации.
Это очень простое приложение. Он начинается с 2 элементов (foo и bar), которые должны быть отображены. В ответ на действие (в данном случае нажатие кнопки) больше данных загружается в состояние и, таким образом, отображается на странице. Все, что вам нужно сделать, это изменить это так, чтобы вместо setTimeout
Вы делаете AJAX-вызов на свой сервер, чтобы получить фактические данные.
Живая версия здесь: https://codepen.io/dpwrussell/pen/qadrko
class Application extends React.Component {
constructor(props) {
super(props);
// Start with 2 records
this.state = {
records: [
{
name: 'foo',
description: 'Some foo'
},
{
name: 'bar',
description: 'Some bar'
}
]
};
// Bind handlers
this.loadMoreRecords = this.loadMoreRecords.bind(this);
}
// Method to call which gets more records on demand
// Here I just use setTimeout and some static data, but in your case
// this would be AJAX to get the data from your server where the callback
// would do the setState. I use a 2 second delay to exaggerate a delay getting
// the data from the server.
loadMoreRecords() {
setTimeout(() => {
this.setState({
records: this.state.records.concat([
{
name: 'hello',
description: 'Some newly loaded hello'
},
{
name: 'world',
description: 'Some newly loaded world'
}
])
})
}, 2000);
}
// Method to render whatever records are currently in the state
renderRecords() {
const { records } = this.state;
return records.map(record => {
return (
<li>{ `${record.name} - ${record.description}` }</li>
);
})
}
// React's render method
render() {
return (
<div>
<h1>List of Records Page</h1>
<ul>
{ this.renderRecords() }
</ul>
<input type='button' onClick={this.loadMoreRecords} value='Load more Records' />
</div>
);
}
}
/*
* Render the above component into the div#app
*/
ReactDOM.render(<Application />, document.getElementById('app'));
Использование https://github.com/css-modules/css-modules-require-hook. Это похоже на babel-register, но для файла.css. По сути, он преобразует ваши требования ('Record.css') в объектную базу javascript в вашей конфигурации ловушек. Таким образом, ваша конфигурация ловушки должна быть такой же, как ваша конфигурация webpack css-loader.
Поместите это в файл входа вашего сервера.
const hook = require('css-modules-require-hook');
hook({/* config */});