question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

A "React for a Python Developer" guide

See original GitHub issue

I think that we should do whatever we can to reduce the barriers of entry in creating custom Dash components. One of the largest barriers to entry is React and JavaScript itself: our community is (by definition) mostly Python developers.

One way that we can help out our community in creating or customizing Dash components is by providing a really friendly, step-by-step guide to creating a Dash component. I’ll call this the “React.js for the Python Developer Guide”.

Below is a rough outline of what I’m imagining. Would love feedback on this!


For Tutorial 1, here’s a rough syllabus that I’ve used in the workshops:

  1. Introduction:

    • React and JavaScript is easier than it seems, you can do it!
    • Most Dash component’s are simple wrappers around existing components. And there are hundreds of thousands of them.
  2. Developer Setup

    • Installing Node, NPM, and create-react-app
      • In practice, it would be nice to use our dash-component-archetype here once we make it better
  3. Making your first change

    • Opening up App.js and changing “React” to “Dash”
    • Observing the hot-reload
    • Making an error and seeing where to find error messages: throw error
    • Doing console.log and seeing the data
  4. Quick React vs Python:

    • React has classes’s like Python classes
    • Declare variables in JavaScript: const and let
    • JavaScript “objects” are Python’s “dict”
      • Except the keys are always strings
    • console.log instead of print
    • import and export
  5. Quick create your own component in the same file as App.js:

    1. Create Header and include it in App:
    class Header extends Component {
        render() {
            return 'Header'
        }
    }
    
    class App extends Component {
        ...
    
        render() {
            ...
            return <Header/>
        }
    }
    
    1. Thread a property through:
        return <div>{this.props.name}</div>
    
        const myHeaderName = 'Dash Header'
        return <Header name={myHeaderName}/>
    
    1. Add another property like style:
        return <div style={this.props.style}>{this.props.name}</div>
    
        const myHeaderName = 'Dash Header';
        const style={'color': 'blue', 'fontSize': 20}
        return <Header name={myHeaderName}/>
    
  6. Making this component Dash-ready:

    • Quick pause: this “component” is hydrated from JavaScript, now let’s make it a standalone Dash component
    • Move it to a new file
    • Add propTypes
    • Run the toolchain
    • Fire up usage.py and have:
    app.layout = html.Div([
        my_component.Header(name='Dash Header', style={'color': 'blue', 'fontSize': 20})
    ])
    - Isn't that amazing? Dash components are 1-1 with their React components
    
  7. Making it more complex with updates and events in react:

    • Making an Input component
    class TextInput extends Component {
        render() {
            return (
                <input value={this.props.value}/>
            )
        }
    }
    
    class App extends Component {
        render() {
            const myValue = 'Text input'
            return <TextInput value={myValue}/>
        }
    }
    
    • Inputs are “controlled”:
      • Note how you can’t enter any text in that input. It’s value is fixed.
      • Note how if you remove value={...}, then you could type into it
      • So, we need a way to handle keypresses and feed those values back into the input
    • Adding an onChange:
      <input value={this.props.value} onChange={(e) => {
          console.log(e.target.value)
      }}/>
      
      • Woah, that (e) => {...} thing? That’s basically like a Python lambda function. Inline, anonymous function.
      • e.target.value? That’s just “something you know”, it’s the standard syntax for input events with JavaScript
    • Start typing and check out your console. Letters!
    • Adding state:
    class TextInput extends Component {
        constructor() {
            this.state = {
                value: 'test'
            }
        }
        render() {
            return (
                <input value={this.state.value}/>
            )
        }
    }
    
    • this.state is a special react class property. We refer to it with this, just like as in python classes
    • React provides a special way to update this.state: this.setState. When you call this.setState, it will call the render component automatically to “rerender” your component. Let’s try it:
    class TextInput extends Component {
        constructor() {
            this.state = {
                value: 'test'
            }
        }
    
        render() {
            console.log('rendering')
            return (
                <input 
                    value={this.props.value}
                    onChange={e => {
                        console.log(e.target.value);
                        this.setState({value: e.target.value});
                    }}
                />
            )
        }
    
    }
    
    • Now type: notice how we’re just renderering and rendering our component. And notice how our input is now getting updated!
    • Now, let’s move the state from TextInput to App:
    class App extends Component {
        constructor() {
            this.state = {
                value: 'test'
            }
        }
        render () {
            console.log('rendering App')
            return (
                <div>
                    <TextInput
                        value={this.state.value}
                        updateValue={newValue => this.setState({value: newValue})}
                    />
                </div>
            );
        }
    }
    
    class TextInput extends Component {
        render() {
            console.log('rendering TextInput')
            return (
                <input 
                    value={this.props.value}
                    onChange={e => {
                        console.log(e.target.value);
                        this.props.updateValue(e.target.value)
                    }}
                />
            )
        }
    }
    
    • data is flowing in a big loop! From the input up to the app, re-rendering the app and re-rendering the TextInput with the new value.
  8. Now here’s the kicker. App? That’s basically dash-renderer. It’s rendering all of the components and it’s providing the data down into the components as props. It also provides an updateValue-like prop, except it’s called setProps and it takes an object. So, to make this Dash-ready, let’s:

    • Move TextInput into it’s own file
    • Add propTypes
    • Rename updateValue to setProps and update the call signature to setProps({value: e.target.value})
    • Run the toolchain
    • Add it to usage.py and create a callback
      • value is now a property that we “listen” to as a callback Input
  9. Now, in practice we won’t create our own components. We’ll frequently just provide wrappers around existing components. Let’s try it out with the react colorpicker:

    • npm install react-colorpicker
      • npm is the pip for node
    • import ColorPicker from 'react-colorpicker'
    • Add this.setProps
    • Add propetypes
    • Run the toolchain
    • Magic
  10. Advanced:

    • If the component’s properties don’t update with callbacks, then it can manage its own state completely. This will be a quite a bit faster as the dash-renderer re-render cycle can take a moment or two.
      • You can check if a component can manage its own state by seeing if this.props.setProps is defined or not.
      • For an example, see the Input component in dash-core-components source
    • We use Ramda as our “standard library”, here’s the docs: https://ramdajs.com/
    • Read the source for the existing components in dash-core-components
    • Subscribe to this issue to be aware of breaking changes in the components: https://github.com/plotly/dash-components-archetype/issues/40

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Reactions:9
  • Comments:17 (12 by maintainers)

github_iconTop GitHub Comments

2reactions
chriddypcommented, Aug 10, 2018

@AmirAlavi - Definitely!

For what its worth, we have a new version that should make this easier: https://github.com/plotly/dash-component-boilerplate. With the new version, you shoulnd’t need to worry about webpack, dev vs normal, hot reloading, etc. You should just be able to follow the new instructions.

For external dependencies, in a nutshell we need a section that explains that:

npm install some-package --save

is the equivalent of pip install and that node_modules folder is basically like a virtualenv folder: local installations.

Also, an explanation of how import and export work and how it’s slightly different than python

2reactions
AmirAlavicommented, Aug 9, 2018

As a mostly Python developer, another major issue I’ve run into besides ReactJS is the javascript toolchain that is required for building a custom Dash component. It’s something you can ignore if you aren’t using external libraries, but as soon as you need to add a dependency, things get confusing. I’ve found it so difficult to understand what’s happening with webpack, webpack.config files, bundle.js, “hot loading”, dev vs “normal” configurations, etc.

Honestly, this has personally been my greatest barrier to creating custom dash components, not learning ReactJS (as someone mentioned above, there are many great tutorials on this from Facebook or even codecademy).

Is there any room for this in the tutorial? I’m thinking something different than the wrapper around react-colorpicker from above. That is already a react component, that doesn’t really require external JS libraries/dependencies, and so doesn’t really touch on toolchain issues.

Read more comments on GitHub >

github_iconTop Results From Across the Web

A Python developer's guide to React - LogRocket Blog
Learn how to use React as a Python developer with this guide and by creating a contact manager application with Flask and React....
Read more >
React for Python Developers: a primer - Dash Plotly
A tutorial on how to program in React and JavaScript for Python developers. ... By the end of this guide, you should feel...
Read more >
React - Full Stack Python
Learn React app is a Git repository with a code tutorial and instructions for how to follow along, as well as exercises to...
Read more >
React to Python: Create React applications with Python
Using a Python-centric viewpoint, this book outlines the developer tools and software libraries needed to develop front-end web applications with Python. It ...
Read more >
Learning React Native as a Python Developer | by Óliver L. Sanz
While the documentation that I have read is full of examples and well explained, It is also fragmented (since you need a lot...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found