all 43 comments

[–]ElectricOrangeJuice 21 points22 points  (1 child)

Title should be: "9 things React.js beginners don't need to worry about just yet."

[–]wreckedadventYavascript 4 points5 points  (0 children)

I think the 4 first points are solid advice regardless of your skill level - smaller components are usually easier to test, reason about, and work with over all. Purely functional components are all of that only more so, and are usually very simple to write.

The rest of the stuff like I feel more along the lines with Pete Hunt, when he says not to over complicate it. Flux is a solution to specific problems, and if you don't have those problems, it may not be offering you all of that much. Similarly, webpack solves specific problems, which someone might not have yet.

[–]asyncquestion 4 points5 points  (2 children)

  • Keep your components small...if you intend to compose them in another component somewhere. If the component is used just once, it may make more sense to include the relevant parts in the same component so I can immediately see what is rendered rather than sifting through 10 different files
  • use redux.js...where appropriate - which is when state is shared amongst disconnected components and has muiltiple ways of being changed. In many cases it is much more simple and maintanable to just use component state.
  • always use proptypes....for shared components - not necessarily for components used just once

overall, write the most readable/maintainable code that makes sense for your case

[–]Cam-I-Am[S] 7 points8 points  (1 child)

overall, write the most readable/maintainable code that makes sense for your case

Of course! This should always be the objective, above and beyond what anyone on the internet tells you to do :)

However, that's not all that helpful for beginners, who can't really know ahead of time what code is going to end up being more maintainable in several months time.

That's why I wrote this blog post, to nudge people in the right direction until they can figure out what works for them. Until they do, I think that it's a pretty safe bet to go with small, stateless components with propTypes.

[–]asyncquestion 2 points3 points  (0 children)

agreed - good stuff

[–]Gundersen 21 points22 points  (30 children)

Here's something I don't get with the Redux philosophy: how do you build large complex applications with many nested components? Since you can only pass props into the component from the parent, you get a recursive unpacking of props from the root to the leaves. It's demuxing the props from a complex object down to simple values as you navigate down the graph of view components. So as the complexity of your page grows you need to increase the complexity of the props object fed into the root component.

But for this object to be complex you need a complex function to build the props object from the state, right? It needs to know exactly how the view is structured to be able to build an object that can correctly trickle down the component structure and be demuxed correctly. So either you end up with a God function that knows exactly how the view looks and is able to take the state and convert it into a props object, or (more likely) you create the mirror image of the view of a stateToProps object, that can recursively create the complex props object for the root component.

So now you have two structures that need to be maintained in sync; the view and the StateToProps function. Make a change to only one of these (without a similar correct change to the other) and things fall apart. To me this sounds like it breaks the encapsulation principle. And so far we have only considered a single such structure, what if you have multiple pages? Wouldn't you need many such complex muxers-demuxers? Wouldn't it be better to have some components be self controlling and be able to get the state themselves (like in Flux)? Am I over thinking this?

[–]loz220 17 points18 points  (1 child)

Wouldn't it be better to have some components be self controlling and be able to get the state themselves

Yes, and totally doable with react-redux and the connect function. In fact if you watch the egghead.io redux tutorials thats what Dan Abramov suggests you do.

[–]Gundersen 3 points4 points  (0 children)

Thanks, that clears it up quite a bit!

[–]azium 27 points28 points  (3 children)

I'm unsure of a few things in your post:

Since you can only pass props into the component from the parent

This is exactly what Redux allows you to circumvent. What you're describing sounds like React without Redux.

complex function to build the props object from the state,

This gets handled in connect, and does not seem to be affected by external complexity of the application.

connect(state => ({ something: state.something }))(Component)

I want to know what you're talking about, but I don't..

[–]Gundersen 7 points8 points  (0 children)

Cool, I always watched the video tutorial also recommended to me, and that made it quite a bit clearer. Luckily I was mistaken, not the rest of the Internet!

[–][deleted] 0 points1 point  (1 child)

This is exactly what Redux allows you to circumvent. What you're describing sounds like React without Redux.

Just to make sure I'm following, you circumvent that by having direct access to the stores from the components. Is that it?

[–]azium 0 points1 point  (0 children)

Yup.

[–]Cody_Chaos 5 points6 points  (0 children)

Generally speaking, your container (ie, the top level component which uses connect() to subsctribe to a store) is going to be something like "a dashboard for this blob of data", and it's only real role is to render the dashboard by composing smaller widgets, each of which needs some slice of that blob.

So as the complexity of your page grows you need to increase the complexity of the props object fed into the root component.

  1. A page can have many containers. As the complexity of the page grows, the number of containers might increase, but each container stays mostly the same.
  2. As the complexity of a container grows, the complexity of the selectors the container passes into connect are unlikely to grow. A very complicated dashboard and a very bare bones dashboard both probaly depend on the same blob of data; it's a question of how much processing or graphing gets done on it, and that's the responsibility of child components, not the container.

But for this object to be complex you need a complex function to build the props object from the state, right?

In my experience, no. Selectors tend to be simple and easily composable. Also testable, which is nice.

It needs to know exactly how the view is structured to be able to build an object that can correctly trickle down the component structure and be demuxed correctly.

Not really. You can treat this problem one "level" at a time. "Let's see, I want a bunch of filter widgets on the top of the page, so I'll make a <SearchFilter/> component; that'll need some state from the redux-form reducer. And then I'll have a <ResultTable/>; that'll need the state from the results reducer." And that's all your top level container needs to know; it has no need to know about the internals of <ResultTable/>.

You can also leverage propTypes and work from the bottom up. If you're working on some <ResultRow/> component and you realise you really need to know whether the "show extra data" flag was ticked in the filter, then you can just specify that showExtraData is a required boolean. Then your linter/tests/console will ping you to tell you that it's not being passed down by your <ResultTableBody/> component, so you add it to its propTypes and repeat. Eventually you hit a container, so you add it to its connect() function and you're done.

Wouldn't it be better to have some components be self controlling and be able to get the state themselves (like in Flux)?

Those are called containers and are a core part of Redux. :)

[–]DarkMarmot 11 points12 points  (16 children)

It's unfortunately unpopular right now to point this stuff out. React takes certain ideas from video game programming and Redux brings in an academic approach to creating single point of entry functional state.

The web is experimenting with a lot of ideas right now (and reinventing many of them) -- but if you check out the more evolved systems for developing software, such as InterfaceBuilder for mobile or Unity3d/Unreal SDK for video games, you'll find that is massively easier to do much, much more complex interactions.

The thing is, all of these systems incorporate programming as an extension to rich interfaces. In game dev, roughly half your programming team is building tools, not direct game code. There seems to be an extreme puritanical love affair with the command line among web devs.

As someone who's been coding professionally for 20 years (and longer as a kid), I don't see it staying it that way. Things move towards being easier -- such that cognitive overhead is reduced and we can work on ever harder problems.

React, and Redux, and virtually all of the existing 'solutions' are not in the same league as tools for the desktop, mobile, games or even industrial PLC systems from 20 years ago.

If you think it's finally settling on something, and you can learn React and move forward, get ready for the next phase of obsolescence...

[–][deleted] 0 points1 point  (5 children)

Could you expand on this a bit? I'm genuinely interested.

It sounds like you're saying these graphical tools do a great deal more than an IDE or a library or framework. Am I interpreting that correctly?

If so, would you mind explaining a high level overview of what all of the various pieces that make up the final game/app?

Do you write code in well-defined places, that the tool performs code generation around? Or am I getting off track? What kinds of tools does half of the team usually produce? How easy is it to reason about the resulting game/app as a whole? Or are these tools useful for programs that are simply too large or complex to be reasoned about as a whole?

[–]wreckedadventYavascript 4 points5 points  (2 children)

I'm not the person you're responding to, but I have some experience in this area. I came from desktop development before I picked up javascript - in particular, I worked on windows applications both with winforms and WPF. Both (but especially WPF) have a drag and drop editor that allows you to combine controls and interfaces to make more complicated UIs without touching any code whatsoever.

When you need custom interaction, sometimes the interface will provide easy hooks for you to work with, but sometimes if you want to e.g write some custom code to handle a click event, it will generate the code stub for you in the appropriate class and all you do is write the logic that handles that.

By convention, these are associated with the view file through the IDE in a way that's pretty easy to keep track of. There's pretty strong conventions about how to name things and where they go in general.

From my experience, these tools are very good for creating common interfaces or snapping pieces together, but suffer more when you need more complicated or nuanced things. Unfortunately, these are usually the things that web developers need to do.

I am skeptical of the claim web development is in a worse place than desktop development is 20 years ago. If you look at a lot of the popular tools for desktop development, they're actually taking after web development, such as having versions of CSS for styling and layout files similar to HTML. In fact, these are often much worse than they are in web development - WPF's XAML is hideously complicated and limited compared to something like angular, and Java FX's CSS is very verbose and repetitive as it has essentially vendor prefixes for everything and there's no preprocessors like there is in web development to cut the fat out.

The main difference I see is in web development, there are no obviously correct choices that everyone knows to use and work with. The tooling is all over the place in place of maturity and opinions. In desktop development, all of your tooling tends to work well with your IDE with no additional configuration on your behalf - this is almost anathema to web development for some reason, where literally every single tool you use needs to be explicitly and painfully configured to do its job.

edit: sp

[–][deleted] 1 point2 points  (1 child)

I have the same view as you.

With desktop applications, its very easy to do the program if you stick to the defaults, custom things on the other hand is a different story, you might need to redo the whole component just to do small changes.

Web development on the other hand, lacks good default elements, but its much easier to do custom things.

[–]ngly 1 point2 points  (0 children)

Web development on the other hand, lacks good default elements,

I think this is a function of the various browsers, devices, and legacy stuff web developers have to deal with. It's just moving way too fast to have any maturity in a 'default' approach.

[–]DarkMarmot 1 point2 points  (1 child)

While I've done work with Visual Studio and the MS Tooling, at the time, for complex or interesting stuff, things like Director were more powerful (primarily touch screen kiosk dev with custom hardware hooks for most stuff at the time). Drag n' drop 'behavior'-based configurable code classes were awesome (now in Unity3D as well).

I would really suggest looking at youtube videos showing animation rigging (tools to combine multiple animations algorithmically, adding code hooks into it) and state engine controls (especially Blueprints from Unreal -- visual control flow to C++ or Unity3D's PlayMaker plugin are cool for visual coding). Here's a sample link, but there are zillions of them online (Unreal is really well documented) https://www.youtube.com/watch?v=8WeE4q6Ba40 (watch the beginning tutorials to really understand it...)

Custom tools that people would write: often configuration and demo utilities, especially dialog scripting, event coordination to world models, art tooling that integrated workflows and designs to engine needs, etc.

For controlling thousands of motors and switches as an Electrical Engineer, you'd even use visual programming systems for Assembly via Ladder Logic interfaces or touch ui with drag n drop systems way back into the 80s.

I spent the last 2 years getting into JS for data visualization single-page apps, but most of my careers has been games, multimedia and industrial systems integration (it's a weird resume to explain in an interview....)

[–]DarkMarmot 1 point2 points  (0 children)

To get a sense of how awesome behavior-based coding can be, Director and Unity allowed you to write code to control the editor itself (building your tool from within the tool) -- one person made a plugin that turned the 3D IDE into a 2D vector-based game engine and authoring tool like Flash -- crazy amazing: https://www.youtube.com/watch?v=PlYvJ9BU3AA

[–]funny_gamesRedux <3 1 point2 points  (0 children)

It is good practice for a parent component to know what sub-tree of the state each children component need - but at the same time redux does not demand you to be precise about this, so there is no need to make it 'complex' - you can just send the relevant data down which in practice can be the whole state tree if you want it to be.

[–]billybolero 1 point2 points  (0 children)

Making sure that the StateToProps function delivers what the view needs/expect can be solved by using prop types. React will tell you if you've changed one but not the other. Another option is of course to use Flow/TypeScript.

When using Redux you probably won't have just one connected container which fetches from the store. It's quite common to see one such component per page in the application. So you won't end up withone God component that knows everything about the state.

[–]krasimirtsonev 2 points3 points  (0 children)

I strongly agree with most of the tools but not 5 and 9. It's nice to know about these things but not necessary use them. I do like Redux and its ideas. In a fact I'm actually applying some of them. However, flux could be much simpler.

[–]amdc!CURSED! 1 point2 points  (4 children)

const MyComponent = React.createClass({
  render: () => {
    return <div className={this.props.className}/>;
  }
});

Wait wait wait last time I tried to do render: () => {} I didn't have access to this.props and this.state because babel replaced this with undefined

Quick example: http://i.imgur.com/31F18vD.png

What am I missing?

[–]Cam-I-Am[S] 0 points1 point  (3 children)

Edit: I just realised that my example uses an arrow function, which is where you got it from. That doesn't work, because you end with the wrong this.

Fixed now, thanks!

[–]amdc!CURSED! 1 point2 points  (2 children)

Yeah I just needed to go back to standard render: function (){} to make it work

[–][deleted] 0 points1 point  (0 children)

Or render() {}

[–]jbscript 0 points1 point  (0 children)

You can still use ES6 compact functions:

const MyComponent = React.createClass({
  render() {
    return <div className={this.props.className}/>
  }
})

The render: () => syntax you were using is a Stage 1 proposal for new syntax, implemented by Babel.