django rest framework and react and redux, oh my!

49
Django Rest Framework and React and Redux, Oh My!

Upload: eric-palakovich-carr

Post on 14-Apr-2017

5.171 views

Category:

Technology


0 download

TRANSCRIPT

Page 1: Django Rest Framework and React and Redux, Oh My!

Django Rest Framework and React and Redux,

Oh My!

Page 2: Django Rest Framework and React and Redux, Oh My!

I’m Eric Palakovich Carr.Co-Founder & Chief Architect at

Previously:

Page 3: Django Rest Framework and React and Redux, Oh My!

What this talk is not

• A comprehensive tutorial

• A deep dive into how these technologies works

• You WILL need to go and learn this stuff on your own after this talk

Page 4: Django Rest Framework and React and Redux, Oh My!
Page 5: Django Rest Framework and React and Redux, Oh My!
Page 6: Django Rest Framework and React and Redux, Oh My!
Page 7: Django Rest Framework and React and Redux, Oh My!
Page 8: Django Rest Framework and React and Redux, Oh My!

{% extends "base.html" %}{% load staticfiles %}

{% block title %}Some Awesome Django Website{% endblock %}

{% block extrahead %} <link rel="stylesheet" href="{% static "some.css" %}"/> <link rel="stylesheet" href="{% static "even_more.css" %}"/>{% endblock %}

{% block body %} <!-- some content in Django template --> <div id="todolist"></div> <!-- more content in Django template -->{% endblock %}

Page 9: Django Rest Framework and React and Redux, Oh My!
Page 10: Django Rest Framework and React and Redux, Oh My!

Javascript Ecosystem

• We’ll be using NPM to manage your packages

• We’ll be using webpack to handle bundling our assets.

• We’ll be using scotch to burn away the memories of configuring the build system for our project.

Page 11: Django Rest Framework and React and Redux, Oh My!

in a nutshell• The pip & cheeseshop / pypi of javascript

• packages.json works like requirements.txt & setup.py

• `npm init` in directory with packages.json generates node_modules. Kinda like a virtualenv directory.

• packages.json also can act like your `manage.py` for your javascript code, but you populate it with custom commands.

Page 12: Django Rest Framework and React and Redux, Oh My!

Building for Javascript• Start coding your project, using `npm install some-package —

save` as you go. This creates and maintains your package.json.

• Setup the config file for your build tool (webpack.config.js, gulpfile.js, Gruntfile, etc)

• Add configs for Babel, minification, and other JS stuff

• Add configs LESS, SASS, and other CSS stuff

• Plus source mapping, tests, linters, sprite sheets, etc

• Run your tool to generate bundles, having them save into your static directory for Django to pick up.

Page 13: Django Rest Framework and React and Redux, Oh My!

{% extends "base.html" %}{% load staticfiles %}

{% block title %}Some Awesome Django Website{% endblock %}

{% block extrahead %} <link rel="stylesheet" href="{% static "bundle.css" %}"/> <link rel="stylesheet" href="{% static "some.css" %}"/> <link rel="stylesheet" href="{% static "even_more.css" %}"/>{% endblock %}

{% block body %} <!-- some content in Django template --> <div id="todolist"></div> <script src="{% static "bundle.js" %}"></script> <!-- more content in Django template -->{% endblock %}

Page 14: Django Rest Framework and React and Redux, Oh My!

{% extends "base.html" %}{% load staticfiles %}{% load render_bundle from webpack_loader %}

{% block title %}Some Awesome Django Website{% endblock %}

{% block extrahead %} <link rel="stylesheet" href="{% static "some.css" %}"/> <link rel="stylesheet" href="{% static "even_more.css" %}"/>{% endblock %}

{% block body %} <!-- some content in Django template --> <div id="todolist"></div> {% render_bundle 'main' 'js' %} <!-- more content in Django template -->{% endblock %}

Page 15: Django Rest Framework and React and Redux, Oh My!

DEMO

Page 16: Django Rest Framework and React and Redux, Oh My!
Page 17: Django Rest Framework and React and Redux, Oh My!

// index.js

import React from 'react';import ReactDOM from 'react-dom';import TodoHeader from './TodoHeader.jsx';

ReactDOM.render( ( <div className="todoWidget"> <TodoHeader listName="todos" /> </div> ), document.getElementById('todolist'));

Page 18: Django Rest Framework and React and Redux, Oh My!
Page 19: Django Rest Framework and React and Redux, Oh My!

// index.js

import React from 'react';import ReactDOM from 'react-dom';import TodoHeader from './TodoHeader.jsx';

ReactDOM.render( ( <div className="todoWidget"> <TodoHeader listName="todos" /> </div> ), document.getElementById('todolist'));

JSX

Page 20: Django Rest Framework and React and Redux, Oh My!

// TodoHeader.jsx

import React, { Component } from 'react';

export default class TodoHeader extends Component { render() { return ( <header className='todoHeadCmp'> <h1>{this.props.listName}</h1> </header> ); }}

Page 21: Django Rest Framework and React and Redux, Oh My!

JSX

// TodoHeader.jsx

import React, { Component } from 'react';

export default class TodoHeader extends Component { render() { return ( <header className='todoHeadCmp'> <h1>{this.props.listName}</h1> </header> ); }}

Page 22: Django Rest Framework and React and Redux, Oh My!

// TodoHeader.jsx

import React, { Component } from 'react';

export default class TodoHeader extends Component { render() { return React.createElement( "header", {className: "todoHeadCmp"}, React.createElement( "h1", null, this.props.listName, ) ); }}

Page 23: Django Rest Framework and React and Redux, Oh My!

export default class TodoTextInput extends Component { constructor(props, context) { super(props, context); this.state = { text: this.props.text || '' }; } handleSubmit(e) { const text = e.target.value.trim(); if (e.which === 13) { this.props.onSave(text); } } handleChange(e) { this.setState({ text: e.target.value }); } render() { return ( <input type='text' value={this.state.text} onChange={::this.handleChange} onKeyDown={::this.handleSubmit} /> ); }}

Page 24: Django Rest Framework and React and Redux, Oh My!

React Component Lifecycle• componentWillMount

• componentDidMount

• componentWillReceiveProps

• shouldComponentUpdate

• componentWillUpdate

• componentDidUpdate

• componentWillUnmount

Page 25: Django Rest Framework and React and Redux, Oh My!

Django Rest Framework• The Web browsable API is a huge usability win for your developers.

• Authentication policies including packages for OAuth1a and OAuth2.

• Serialization that supports both ORM and non-ORM data sources.

• Customizable all the way down - just use regular function-based views if you don't need the more powerful features.

• Extensive documentation, and great community support.

• Used and trusted by large companies such as Mozilla and Eventbrite.

Page 26: Django Rest Framework and React and Redux, Oh My!

Model->Serializer->ViewSetclass Todo(models.Model): text = models.CharField(max_length=300) marked = models.BooleanField(default=False) class TodoSerializer(serializers.HyperlinkedModelSerializer): class Meta: model = Todo fields = ('id', 'text', 'marked')

class TodoViewSet(viewsets.ModelViewSet): queryset = Todo.objects.all() serializer_class = TodoSerializer

Page 27: Django Rest Framework and React and Redux, Oh My!

Demo

Page 28: Django Rest Framework and React and Redux, Oh My!

Three Principles of Redux

• Single source of truth

• State is read-only

• Changes are made with pure functions

Page 29: Django Rest Framework and React and Redux, Oh My!

Redux State Tree / Store{ visibilityFilter: 'SHOW_ALL', todos: [ { text: 'Consider using Redux', completed: true, }, { text: 'Keep all state in a single tree', completed: false } ]}

Page 30: Django Rest Framework and React and Redux, Oh My!

Reducers{ visibilityFilter: 'SHOW_ALL', todos: [ { text: 'Consider using Redux', completed: true, }, { text: 'Keep all state in a single tree', completed: false } ]}

Page 31: Django Rest Framework and React and Redux, Oh My!

import * as types from '../constants/ActionTypes';

const initialState = [];export default function todos(state=initialState, action) { switch (action.type) { case types.ADD_TODO: return [...state, action.todo]; case types.DELETE_TODO: return state.filter(todo => todo.id !== action.id ); case types.EDIT_TODO: return state.map(todo => todo.id === action.todo.id ? action.todo : todo ); default: return state; }}

Page 32: Django Rest Framework and React and Redux, Oh My!
Page 33: Django Rest Framework and React and Redux, Oh My!

store.dispatch({ type: 'ADD_TODO', todo: { text: "Check how much time is left", marked: false }})

store.dispatch({ type: 'SET_VISIBILITY_FILTER', filter: 'SHOW_COMPLETED'})

Page 34: Django Rest Framework and React and Redux, Oh My!

Presentational Components• Are concerned with how things look.

• Use props for displaying everything

• Do not manage state at all

• Don’t emit actions, but may take callbacks that do via props

<MyComponent title=“No state, just props.” barLabels={["MD", "VA", "DE", "DC"]} barValues={[13.626332, 47.989636, 9.596008, 28.788024]}/>

Page 35: Django Rest Framework and React and Redux, Oh My!

Container Component• Are concerned with how things work.

• Responsible for providing data to presentational components via props

• Also responsible for handling state changes triggered inside a presentation component via callback prop. These state changes are often done via dispatching an action.

Page 36: Django Rest Framework and React and Redux, Oh My!

class TodoApp extends Component { componentDidMount() { this.props.actions.getTodos(); } render() { const { todos, actions } = this.props; return ( <div> <Header addTodo={actions.addTodo} /> <MainSection todos={todos} actions={actions} /> </div> ); }}function mapState(state) { return { todos: state.todos };}function mapDispatch(dispatch) { return { actions: bindActionCreators(TodoActions, dispatch) };}export default connect(mapState, mapDispatch)(TodoApp);

Page 37: Django Rest Framework and React and Redux, Oh My!

Wiring Redux to DRF

• Python package “django-js-reverse" for getting your url routes in your javascript

• NPM package “redux-promise”

Page 38: Django Rest Framework and React and Redux, Oh My!

import * as types from '../constants/ActionTypes';

function deleteTodo(id) { return fetch(Urls.todo_detail(id), { method: 'delete', headers: { 'Accept': 'application/json', 'Content-Type': 'application/json', 'X-CSRFToken': getCookie('csrftoken') }, }).then(() => ({ type: types.DELETE_TODO, id: id }));}

// In a component somewhere elsestore.dispatch(deleteTodo(this.props.todo.id))

Page 39: Django Rest Framework and React and Redux, Oh My!

import * as types from '../constants/ActionTypes';import * as api from ‘../path/to/MyApiLibrary';

function deleteTodo(id) { return api.deleteTodo(id).then(() => ({ type: types.DELETE_TODO, id: id }));}

// In a component somewhere elsestore.dispatch(deleteTodo(this.props.todo.id))

Page 40: Django Rest Framework and React and Redux, Oh My!

DEMO

Page 41: Django Rest Framework and React and Redux, Oh My!

Quick Recap i.e. TL;DR

Page 42: Django Rest Framework and React and Redux, Oh My!

You need a build tool to create bundles.

Webpack is nice for this.

Page 43: Django Rest Framework and React and Redux, Oh My!

{% extends "base.html" %}{% load staticfiles %}

{% block title %}Some Awesome Django Website{% endblock %}

{% block extrahead %} <link rel="stylesheet" href="{% static "bundle.css" %}"/> <link rel="stylesheet" href="{% static "some.css" %}"/> <link rel="stylesheet" href="{% static "even_more.css" %}"/>{% endblock %}

{% block body %} <!-- some content in Django template --> <div id="todolist"></div> <script src="{% static "bundle.js" %}"></script> <!-- more content in Django template -->{% endblock %}

Page 44: Django Rest Framework and React and Redux, Oh My!

// index.js

import React from 'react';import ReactDOM from 'react-dom';import TodoHeader from './TodoHeader.jsx';

ReactDOM.render( ( <div className="todoWidget"> <TodoHeader listName="todos" /> </div> ), document.getElementById('todolist'));

Page 45: Django Rest Framework and React and Redux, Oh My!

// TodoHeader.jsx

import React, { Component } from 'react';

export default class TodoHeader extends Component { render() { return ( <header className='todoHeadCmp'> <h1>{this.props.listName}</h1> </header> ); }}

Page 46: Django Rest Framework and React and Redux, Oh My!

class Todo(models.Model): text = models.CharField(max_length=300) marked = models.BooleanField(default=False) class TodoSerializer(serializers.HyperlinkedModelSerializer): class Meta: model = Todo fields = ('id', 'text', 'marked')

class TodoViewSet(viewsets.ModelViewSet): queryset = Todo.objects.all() serializer_class = TodoSerializer

Page 47: Django Rest Framework and React and Redux, Oh My!

import * as types from '../constants/ActionTypes';

const initialState = [];export default function todos(state=initialState, action) { switch (action.type) { case types.ADD_TODO: return [...state, action.todo]; case types.DELETE_TODO: return state.filter(todo => todo.id !== action.id ); case types.EDIT_TODO: return state.map(todo => todo.id === action.todo.id ? action.todo : todo ); default: return state; }}

Page 48: Django Rest Framework and React and Redux, Oh My!

import * as types from '../constants/ActionTypes';

function deleteTodo(id) { return fetch(Urls.todo_detail(id), { method: 'delete', headers: { 'Accept': 'application/json', 'Content-Type': 'application/json', 'X-CSRFToken': getCookie('csrftoken') }, }).then(() => ({ type: types.DELETE_TODO, id: id }));}

// In a component somewhere elsestore.dispatch(deleteTodo(this.props.todo.id))

Page 49: Django Rest Framework and React and Redux, Oh My!

Thanks!Eric Palakovich Carr

@bigsassy on twitter and github example repo at https://github.com/bigsassy/drf-react-redux