Redux & Django. Initial State
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(/"/g, '\"')) }
window.__INITIAL__ = {
event: parse(''),
users: parse(''),
}
</script>
Преобразование в строку JSON и последующий парсинг в шаблоне выглядит излишним,
но беда в том, что JS не умеет работать с примитивами Python. Банально True
в
python, в JS - true
. ParseError. Поэтому нужно приводить к общему виду.
Еще момент за replace(/"/g, '\"')
: в шаблон сериализованный объект
приходит с espace-char’ами, поэтому кавычки нужно вернуть обратно.