I'm a huge ReactJS fan, but right now I'm doing some development with Django and plain old HTML/JavaScript template forms and I'm finding it incredibly easy and my general pain level seems to be lower. I haven't figured out why exactly.
Probably I'm just not doing anything very sophisticated. It's just a plain old form driven website - that would account for it.
When to use the more powerful tools is an important (and tricky) lesson to master. Not every project needs React.
Lately I've been writing little personal projects using Vanilla JS. There's something rather therapeutic about limiting one's self to zero dependencies. I'm wildly surprised every time I come back to Vanilla JS to see just how many core features there are. I can do modules in the browser now! Yippee!
And beyond that, not even using JS and just using Django Templates or Jinja is great too.
But I write a lot of software that monitors and controls mobile robots in warehouses. For that kind of wild state management of 100+ data sources, all with their own incomplete states, controls, unpredictably erroneous behaviours, React + Redux is just a godsend.
One of the things that makes it hard to choose which technology you begin with is that small projects don't stay small, even if you thing they will. So the risk is I think "hey it's s small project, I'll whip it up in Django", and then of course in six months I'm cursing myself for not starting in React.
I think that part of it is just experience. You'll slowly learn to better predict which projects are likely to grow, especially in a way that needs a more expressive foundation.
I also think that the, "aw crap I have to re-write this from Django Templates to React" isn't exactly a bad thing. You've probably learned a ton about the problem you're solving by focusing on the problem directly in front of you[1] rather than trying to plan for the future problems that you don't quite understand yet. So when you tear it down to build the next iteration, the code you're replacing wasn't the valuable part.
[1] Not all projects are organic. But the ones that are, really benefit from a, "get this out in 2 weeks and learn what we don't yet know about it" rather than spending months trying to perfect some product that we're mostly just guessing at.
I'm likely giving a talk on this exact subject in January (depending on scheduling). If you're curious about the various approaches I've tried, you can reach me at this username in all sorts of places.
I recently just started replacing some jQuery functionality with React in a large Django project, using Django-Rest, it's actually been less complicated than I expected.
At work we are building a simple CRUD admin with Jekyll and Vue as a jQuery replacement. No babel, no webpack, no router, no Vuex. The complexity has been reduced immensely.
Data still comes from an API, so the front end is still decoupled from the back end, and anyone that is not a JS ninja can still contribute to the codebase since the project structure is really simple.
This is an internal project so we can tell our users to use latest Chrome to avoid transpiling and such, but configuring webpack would still be possible.
I really recommend the approach.
A lot of people think getting the data from an API automatically means building a single-page-application while in fact you could use this approach with Jekyll to create a static site, or even use server side code to generate dynamic markup and still consume an API.
It's very early on, but essentially, completely replaces the template rendering with React components. Still regular markup, but whenever you need dynamic behaviors, it's trivial. And it's all server side rendered.
You can see the traditional Django context becomes "Props" in the top level component. Then it's React all the way down.
Notes:
1. The most complicated part is the initial setup. You do need to run NodeJS, webpack + Django server. Working on improving that.
2. I like TypeScript and use it here. But theoretically it'll be optional. The Django+Python part is also statically typed using MyPy.
3. No instructions whatsoever yet. But you can see a live site using this stack here: https://www.silviogutierrez.com/ . Notice it's server rendered but has dynamic behaviors that are trivial in React but harder with jQuery + Django. Example: https://www.silviogutierrez.com/blog/making-cck-fields-read-... Look at the nested commenting and moving the form around. Very easy in React.
4. Because of the architecture, adding a much-better-turbolinks style Ajax is trivial. Click around the site above (loading indicator not yet added). The page is re-rendered entirely on the client but gets a server AJAX response.
Hope that's interesting info. If you'd like to try it out, definitely let me know. Once you overcome the setup hurdles, it's amazingly productive. As in, if all you wish to do is `{{ form }}` like old school Django, here's the equivalent sample template: https://github.com/silviogutierrez/reactivated/blob/master/c...
Neat! In this case, it took a lot of work to get the forms "fielded" in React world. So you can individually render fields, etc. But yea, setup is currently a pain.
I have a quite very crude implementation of form fields on my side, which annotates the type of formfield (as a string) along with several other useful things, like id_for_formfield, html_name etc.
Have you measured the efficiency gains? On your site, you are making large scale changes as you click from link to link, so there isn’t much of the ui you aren’t re-rendering.
In the site you linked to, the scroll position gets messed up as you go back and forth between “pages” and click on links — problems that don’t occur when you fully re render a page.
Efficiency in coding: inmeasurable. For typical CRUD it's amazing once you get over the hump of setup.
Efficiency in speed: likely very little over just requesting the HTML via AJAX.
As far as scrolling/etc: that behavior is super buggy and I never really tested it. I "turned on" the turbolink-esque behavior as a test but it needs far more work.
In any case, one can just turn it off and revert to regular SSR behavior instead of the AJAX-ey one. I might even do that because, in general, I want my page to show the traditional loading icon in place of the favicon.
this is sooo cool. Can you build this for Flask as well - basically Jinja2. I do believe that Django can use jinja2 as well.
However, would like to compile all the reactjs stuff before including it in flask/django.
You could look into the https://github.com/nozzle/react-static project to use their static compiler (which does React -> static html/js) to achieve this exact thing.
Not a bad idea! In this case though, a major element I wanted from Django was the ability to use its forms "as is" with all the validation powers and ease of doing CRUD. Server agnostic would just be taking JSON -> React.
With the addition of `React.memo`, is it still the recommendation from the React team that we only use `React.PureComponent` and `React.memo` in places where we profile and identify performance bottlenecks?
I seem to remember reading that adding something like `PureComponent` or implementing `shouldComponentUpdate()` can actually slow things down due to the cost of props/state comparison?
Either way thanks for another great release team! Suspense has me super excited!
Every time I see stuff like this it just makes me think, why does the developer have to care about this? For example take Glimmer, you never have to do `shouldComponentUpdate` or anything like that, it's just maximally performant out of the box.
Great work from the React team on this release - it's exciting to see some big enabling features like suspense and lazy being baked into the library (rather than falling back on solutions like react-loadable).
One nice feature of react-loadable is that you can specify a threshold (300 ms by default I think) which is used to prevent rendering of the loader until after the threshold is passed so you don't get a flash of the loader. Users can perceive it as being slower if you have a quick flash of a loader then show the component.
I haven't seen anything yet about the Suspense component supporting this. I imagine you could wrap the suspense component with your own to achieve this behavior, but it's nice not to have to reimplement.
>One nice feature of react-loadable is that you can specify a threshold (300 ms by default I think) which is used to prevent rendering of the loader until after the threshold is passed so you don't get a flash of the loader. Users can perceive it as being slower if you have a quick flash of a loader then show the component.
There is more nuance to it — essentially, React Loadable renders a _hole_ instead of the spinner in this case. Which isn't much better than a spinner because you still see the intermediate state.
With the current release of Suspense, you can do it if your fallback component renders spinner after a timer. So that's not difficult. But we also don't think it's good either.
Instead, when we release Concurrent Mode, you can _avoid showing the change altogether_ until a certain threshold passes. That's the `maxDuration` prop (which doesn't do anything outside of Concurrent Mode).
So you don't even show a hole. Instead, the whole UI is "suspended". And then the fallback kicks in if takes too long.
I am wondering how to avoid unnecessary re-renders using `contextType`. With the render props pattern, you could write a component e.g. <Subscribe> that subscribes to a store and accepts a prop to indicate the specific data dependencies of your component (similar to mapStateToProps() in redux -- here it could be called mapContextToProps()). It's nice to be able to use `static contextType` but it would re-render anytime any property of your context object changes (just as would be the case when using a Consumer directly). That might be fine for something like a theme but wouldn't scale to a more general state management solution.
I was definitely mis-understanding functional components because I'd have assumed that memo was the default behaviour. Could anybody with more experience/knowledge suggest what sort of functional components you'd want to re-render if their props don't change? Cool that there's an easy way to get that behaviour now though! :)
Unfortunately there is a long backlog of PRs to the React docs waiting for review so I don't know if/when this info might be incorporated into the docs. Also React is evolving so fast that it would need to be updated, e.g. to mention memo, and given that fast evolution I can understand why there's a backlog. But I do hope that someone on the React team eventually has time to look at adding more explanation to the "Optimizing Performance" section.
By default, React doesn’t check if individual props are equal. This is for two reasons:
1. We support using mutable objects in props. Even if a prop is reference identical to the last render, the component might be reading some property of it that has changed.
2. Checking equality of props takes time. In the (common) case where a parent rerenders and it’s children need to change in response, any time we spend comparing will be extra overhead on top of the actual render cost. Often rerendering is fast anyway and adding more comparisons only makes it slower.
Because of these, we don’t do these checks by default. Instead, we recommend adding memo/PureComponent/shouldComponentUpdate in places where you know it will make a difference.
I still need to go find my "aha!" moment for contexts. I get them but I haven't developed that intimacy where I know when I should use them.
Also I'm finding it trickier to know which method for component definition to reach for. I love that we have freedom of choice. But I struggle to pick between classes (pure and not), class methods (perhaps to clean up big render() methods or define class-relevant subcomponents), and functional components (memoized or not). I had someone getting into React asking me about it and I didn't have a really solid answer. I think I just confused them. This is probably just a tutorial/documentation/examples kind of problem.
We use it for application-wide stuff that would need to be drilled down several layers, and isn't state. So -- as a contrived example -- if we have a form that submits to a configurable URL (configurable at build time), then we wrap that URL up in a context. The eventual FormComponent will then consume the URL from context, rather than being drilled through n-layers of React components as a prop. Redux isn't the right answer here, because that URL's never going to change, but it used to do the job in a pinch.
Other examples are react-redux itself (which uses the legacy context API) or react-intl (which uses the legacy context API), or a themeable widget set. You put a wrapping context at the top of your tree like <Provider>, <IntlProvider messages={someMessages} locale={this.state.locale}> or <ThemeProvider theme={myEmployersColours}>, and then nested deeply in the application you use a <Message> that will look at the context provided by the IntlProvider, or the context provided by the theme, to pull out the actual message/colors it should show.
Basically, context is useful for encapsulating cross-cutting concerns :).
Aha. Okay I think I'm having a moment. I could possibly use this to pass a reference to a websocket stream for streaming data that's way too high frequency to be handled with redux actions.
Say, 100 robots driving around, displayed by a map component. I want to handle the addition of removal of a robot as an action but the actual 10hz pose updates can just be handled by the canvas and ignored by react entirely.
Maybe even context for camera streams too.
Previously I would just handle a websocket stream as a global. Yuck.
Note that context updates do require that React walk over the component tree to find the appropriate consumers, and that itself has a cost. In fact, at the moment, it seems to be _relatively_ expensive, per the discussion in this issue : https://github.com/facebook/react/issues/13739 .
We're actually working on converting React-Redux to use `createContext` in version 6. I had hoped that it would be a big performance improvement, but unfortunately our (admittedly limited) perf benchmarks indicate that the experimental v6 branches are slower than our current v5 release build. In v5, the individual connected components subscribe to the Redux store, and can bail out of calling `setState()` if no update is necessary. In v6, we've only got one subscription (in `<Provider>`), but any Redux store update requires that React walk the tree and update the context consumers so they can run `mapState`. So, React _always_ gets involved, whereas before we might skip React if nothing had changed.
Per that issue, I'm hopeful that the React team can optimize deep context updates in the near future.
I've got apps where I am passing props down a few levels (perhaps three components deep). What I don't completely understand if Context is a _better_ solution for what I am doing or if it is just another way to accomplish the same thing.
I hear you. I usually use Redux and I find myself `connect`ing a lot more things than I used to. So far I haven't found any seriously painful reasons to do so. Like each tab of my phone app is connected. Each major "concept" in my app is connected. Generally everything above connected components are purely layout/app navigation and it seems to work. I'm betting Dan would suggest it's not necessarily a bad idea and might be fine.
I suppose context is a way of doing that. But I'm just don't grok it yet. I should experiment a lot more.
Generally, connecting more components to Redux is better for performance. The cost of more `mapState` calls is less than the cost of more "wasted" renders, and when a component needs smaller pieces of the Redux state, other state changing means it's not affected.
See my post "Practical Redux, Part 6: Connected Lists and Performance" [0] and the Redux FAQ entry on using React-Redux [1] for more details.
Also, we're completely rewriting the React-Redux docs from scratch, and they now have their own site [2] . We've got some new tutorial material available, and a guide section on writing `mapState` functions. The new section on using `mapDispatch` should be up soon, and we've got a lot more planned, including sections on writing selectors, performance optimizations, and how React-Redux works internally.
Where I'm at we were putting refs into redux, but since HTML elements are mutable they don't quite belong in redux. So moved them into an API where the refs can be passed down the tree with contexts. Then use those refs for rendering portals. Useful for having content be able to manage a panel elsewhere on screen
The other angle to solving this problem would be adding lifecycle methods to React.Context (instead of using render props), which could eliminate the need for multiple contexts. Making Consumer contexts more efficient & composable.
The contextType API serves as a convenience for the most common case of accessing context today. While the existing render prop API is more versatile, the fact is it's awkward in some cases with classes (e.g. when you need to access it in lifecycle).
And unfortunately that means that people are stuck using the legacy context API which is even worse (it makes React bigger and slower). So we're adding a convenience to help people migrate to the new implementation with a slightly more familiar syntax.
I guess in a way it _is_ a compromise, but in our view it's better than if people just kept using the legacy context API.
contextType API looks great. I thought when I saw the new context API that it looked neat from a code cleanliness point of view, but a bit of a pain to use. This looks much easier :)
ClojureScript dev here, we use the context pattern a lot in http://www.hyperfiddle.net/ and we feel it does not harm our ability to reason about referential transparency
It's just another input. Previously, React derived a rendered set of virtual-dom nodes from `props` and `state`. Now, it' derives that set of nodes from `props`, `state` and `context`. It's useful syntactical sugar.
What do you mean by "support for SSR"? Can you elaborate?
All our releases support SSR. But some specific features need to wait for a new async server renderer. I can't tell you when that's going to happen although it's most likely within 2019.
I'm talking about react Suspense for SSR. The blog post says "Note: This feature is not yet available for server-side rendering. Suspense support will be added in a later release.".
Is there an RFC somewhere about that new async server renderer?
Probably I'm just not doing anything very sophisticated. It's just a plain old form driven website - that would account for it.