Issue

Переписывая Банк на Redux, потребовалось решить вопрос о том, как инициализировать первичное значение. У меня там уже были хаки в виде аттрибута data-id на форме, который мне сообщал id события. До redux у меня форма была шаблоном jade, и следовательно, поля заполнялись через этот шаблон еще на сервере:

form(data-id=4)
    input(type="text" id="event-name" value="")

Но теперь форма - React-компонент, а состояние - Redux-store. Что бы наполнить его с сервера, нужно либо делать перед рендерингом запрос данных через API, либо применять магию. Магия существует, и не совсем это магия.

Сначала конечно же я сделал все через запрос: сначала рендерим некий ProgressBar, и в это время запрашиваем данные. Как только мы их получили - рендирим целевой компонент.

Хотя я и поиграл чуть-чуть с Promise’ми, но выглядело это ужасно. Странно, что получив страницу с сервера, мне нужно еще и что-то у него спросить.

Конечно лучше всего - Server Side Rendering применить уже и не париться. Но в случае с Redux, мне все равно придется каким-то образом наполнить store начальными данными. Да, как вариант, после рендеринга прошустрить отрендеренное и поспрашивать у html данные, но это еще более убого.

Предлагаемое решение в Redux - наполнять глобальную переменную window.__INITIAL_DATA__ данными. В принципе, это самое лучшее решение. Идея проста: в обработке запроса мы генерим html-response, и вставляем в head например, script где и выполняем присваивание window.__INITIAL_DATA__.

Django & Jade

Django отдает моему jade-шаблону данные. Сначала(когда была html-форма) я отдавал просто объектом и внутри вытаскивал из него данные в каждое поле. Но теперь мне нужно было отдать объект целиком, причем как Object JS.

def eventDetails(request, pk):
    event = get_object_or_404(Event, pk=pk)
    context = dict()
	context['event'] = json.dumps(EventSerializer(event).data)
	return render(request, 'banking/event.jade', context)

Здесь я наполняю контекст данными события: сереализую модель через EventSerializer в python’овский dict, а затем преобразую все это в строку-JSON и отдаю в шаблон jade. Это именно строка, в которой лежит “сериализованный” JS Object события.

В шаблоне, в head-теге парсим объект и запихиваем его в window.__INITIAL__:

<script>
function parse(data) { return JSON.parse(data.replace(/&quot;/g, '\"')) }
window.__INITIAL__ = {
	event: parse(''),
	users: parse(''),
}
</script>

Преобразование в строку JSON и последующий парсинг в шаблоне выглядит излишним, но беда в том, что JS не умеет работать с примитивами Python. Банально True в python, в JS - true. ParseError. Поэтому нужно приводить к общему виду.

Еще момент за replace(/&quot;/g, '\"'): в шаблон сериализованный объект приходит с espace-char’ами, поэтому кавычки нужно вернуть обратно.