7 ms·
Things Reacters do that Re-framers avoid
- hartator 9y ago'componentDidMount' doesn't exist anymore in React es6.
- haukur 9y agoIt still does (these docs use the ES6 class API): https://facebook.github.io/react/docs/react-component.html#componentdidmount https://facebook.github.io/react/docs/react-component.html#c...
- amelius 9y agoHow would this work in re-frame: Let's say I have a box with 1000 items. It will take some time to load, so those 1000 items should not be painted in one go (freezing the UI), but instead be shown incrementally, from top to bottom. Imagine that while it is loading, I can click a "delete" button on one of the items, so that item would disappear while the list is still growing at the bottom.
- TheAceOfHearts 9y agoYou create a virtual list, only rendering the items visible in the viewport. Use intersection observer or scroll events to find out when you're about to go past the selected item.
- amelius 9y agoDoesn't that cause either stuttering, or flickering in the viewport?
- jaggederest 9y agoWhen I did this back before ajax was a thing, it was by using image elements that were moved like a treadmill, we managed those so that there was a buffer outside the screen area that was pre-filled to avoid stuttering. Essentially we rendered ~1.5 screens wide / long and would fill them in a non-blocking way when the buffer was reduced.
- amelius 9y agoBut when you click the scrollbar and drag it down, you can easily make the viewport scroll by more than 2x its height in a matter of milliseconds. I experimented with this myself, and the UI designer I worked with thought it was not pretty when the screen turned blank while scrolling rapidly. The problem I had was that painting the items in the viewport took already more time than the allotted time per frame.
- Groxx 9y agoSome implementations provide placeholders that are quick to render (e.g. a single static image, no deep DOM/view tree) to work around this kind of thing. In my experience on both android and web it tends to work pretty well - even very low-end hardware can do this quickly enough to be invisible, and if you are able to drop down into something that can do instanced rendering it's about as close to "free" as possible. Whether the placeholders look any good is a different issue. We generally thought they looked / transitioned to real content a lot worse than showing nothing, and eventually just ripped them out. But e.g. Pinterest did it fairly successfully for a long time (they tended to replace images with a solid image-background-color so the content just kinda emerged. neat effect, but works far better with product images than user-generated content :) ) But ultimately, when you exceed your tolerances, you have to render something or nothing, or disallow it (e.g. block everything). You just have to choose which one. The point where you exceed will shift depending on what you're using/doing, but it always exists.
- darkmarmot 9y agoThis means the code has issues. I have virtualized data grids holding thousands of records with each cell incorporating d3 visualizations and this does not happen.
- ridiculous_fish 9y agoDo you have a link you can share?
- 9y ago
- TheAceOfHearts 9y agoIt depends on your implementation. This isn't a new problem, it also exists in native applications. If it takes a long time to render each item, you might consider using a placeholder and caching existing elements. Be sure to track how much time is spent rendering so you run at 60FPS.
- frigen 9y agoI agree that reactjs would have been better without setstate, instead with tightly integrated Redux, which would remove much of the Redux boilerplate. For the most part, this is what this reframe thing aims at as far as I can tell. Setstate really should be long term deprecated, it's a design error in react.
- simoncarter 9y agoI agree, and try to write all my react without it, using redux, thunks and reselect heavily. I think it's easy to say it was a design error with hindsight. I'm happy React came along, and in the future it will either get better or we'll move on to something else, heaving learnt from it's mistakes.
- frigen 9y agoMy theory is that any technology that can be simpler will be replaced by one that IS simpler. New technologies like react either need to fix their problems like lack of integrated state management or be replaced by something that does do it right. The criticisms of the linked post are valid.
- taeric 9y agoThis flies in the face of the proliferation if js frameworks. Mayhap each simplified something, but the result is more complex. Frighteningly so.
- BigJono 9y agoThat's a symptom of people not understanding the concept of complexity and falling victim to the law of leaky abstractions. People don't work towards reducing complexity in large applications (which involves trimming dependencies, removing api surface area and minimizing interactions between different people's code, which is all hard), they work towards reducing complexity in simple toy applications (which is about cramming as many tools in until you can do exactly one specific thing in one short line and it looks nice). That has the effect of reducing complexity at first glance, but increasing it in real world applications.
- fiatjaf 9y agoWhat about setting a value deeply nested in your state when you change something in a deeply nested component? What if that value is inside an array?
- gleenn 9y agoOnly the portion that changes will be rerendered because of the way Clojure shares nested data structures when there are changes.
- riwsky 9y agoNot quite: while Clojure does share nested data structures, and that does allow for some neat tricks around fast comparison operations, the fact that only changed SUV trees rerender is all due to react, and its shouldComponentUpdate. A normal js app can get the same results, if it wants.
- hakanderyal 9y agoI've built a lot of apps with React/Redux, both complex and simple ones. At first there were lots of boilerplate code, and lots of kind-of-similar-but-different code all around. After each project, I extracted and generalised the helper components/methods/systems to create my own 'framework', and now I have a foundation that eliminates most of the pain points that people experience with react/redux, that's specific to the way I develop software. Thats why I love React and surrounding ecosystem, it allowed me to choose the relevant libraries/solutions that fits my workflow. Here is my thoughts about the points in the article: 1. Reacters load data on mount In my components, I just declare the data that it needs, and the relevant system loads the data and sends it to the component via props. (like Relay) No requests happen in the component directly. When you have only a few components that needs data in your app, fetching it in the component works, but when you have a complex app (I build ERP systems) you need a centralised way to handle data fetching. 2. Reacters register a bunch of event handlers in their components Declarative event-binding works great for me (similar to react-event-listener[0]). Instead of adding the subscribe/cleanup logic to every component, I just declare the events I'm interested in, and just add the relevant handling code to my component. 3. Reacters optimize when to render Using redux and never overwriting the store takes care of this for me. 4. Reacters load data when stuff changes Same as 1., yon can declaratively state what you need, and the relevant system can handle the rest of the logic without changing anything in the component. 5. Reacters worry about when to set state I'm not sure if this is really a problem, especially when you learn how the lifecycle hooks work. 6. Reacters use a lot of Redux boilerplate Redux has a goal to keep things simple, and let users choose the relevant 3rd party solution to your needs. It means that you need to do some work to create a no-boilerplate solution, but in the end it will work flawlessly according to your needs. In my 'framework', I generate the store definitions and action handlers for my database models automatically from SqlAlchemy model definitions, thus eliminating 95% of the boilerplate. I know that there are frameworks out there that eliminates the need to create your own solutions to most of these problems, but I've found out that, when you try to go out of the 'blessed' path, you will be banging your head to the wall more times than you want. With building my own solutions around the react/redux, I'm in control of the things that I care about. When you control the 'magic' part of the stack you use, you have a lot of power in your hands when problems arise. [0]: https://github.com/oliviertassinari/react-event-listener https://github.com/oliviertassinari/react-event-listener
- erokar 9y ago> 1. Reacters load data on mount. I want my Views to be pure. They need to take some data and output DOM. At least this item comes off as a straw-man argument. Reacters also want their views to be pure. They do not typically load data in presentational components, and it can be easily avoided. That said, granted: Clojure, Elm et al. achieves purity and immutability in a simple and clean way JS/React/Redux can only approximate. The latter is for the dirty pragmatists among us, I guess.
- Groxx 9y agoSomewhat strawman, yeah. But it still seems valid - React allows you to do this, and you do see it in the wild. People who have been bitten by it (or read enough best-practices stuff to avoid it up-front) will know better and won't do so, but you have to know better - that's kinda the central point in here. React has more footguns, and the article is arguing that they're unnecessary / things end up worse than if they weren't allowed, without losing flexibility.
- ridiculous_fish 9y agoHow do Re-framers handle components that wants to redraw using a timer, such as an animation or progress bar?
- always_good 9y agoMaybe it'd be like Elm where you can subscribe to external events, as if you were to do something like this: requestAnimationFrame(() => dispatch('TICK', Date.now() - prevTick)) Then you can feed the offset into view functions which forces a re-render and steps the animation.
- serpix 9y agoyou would normally start setInterval/whatever function somewhere and you dispatch the change to re-frame when needed. Reframe will update the db and the components subscribing to that data will redraw when a change occurs. The component(s) themselves have no coupling whatsoever to what is providing the displayed data.
- rmrfrmrf 9y agoBy chance, I stumbled upon this same article a few weeks ago while re-learning React and learning Redux. I didn't get much out of the article since gripes 1-5 are all solved by Redux, and 6 is a complaint about Redux having too much boilerplate. It also seemed to me that mapStateToProps and mapDispatchToProps aren't given a fair representation in this article (especially with the "selector" pattern emerging within them). If your Redux store is denormalized already, then yes, mapStateToProps will seem quite redundant. However, if you're working with multiple sets of async data, it's much easier to organize your store by fetch method and denormalize inside mapStateToProps.
- acemarke 9y agoYep, and as I've said numerous times [0] [1]: you can use as much or as little abstraction on top of Redux as you want. Don't like writing action constants by hand? Use `redux-actions` to generate action creators that have an overriden `toString()`. Don't like touching multiple files? Use the "ducks" pattern. Want something that adds additional layers on top so you don't even have to touch the store? Use Kea or Jumpstate or Dva. Also, my own personal advice is that you should always use the "object shorthand" version of `mapDispatch`, and never actually write a real `mapDispatch` function by hand again: const actions = {addTodo, toggleTodo}; export default connect(mapState, actions)(TodoList); [0] http://blog.isquaredsoftware.com/2017/05/idiomatic-redux-tao-of-redux-part-2/ http://blog.isquaredsoftware.com/2017/05/idiomatic-redux-tao... [1] https://github.com/reactjs/redux/issues/2295 https://github.com/reactjs/redux/issues/2295
- pandeiro 9y agoHaving to use something like Redux, conceptually solid but so full of boilerplate, instead of re-frame is kind of like having to use Java at work instead of Clojure. Some of us are just lucky, I guess.
- tigroferoce 9y agoSo true. Some of us are lucky enough to use a concise language like clojure. I am really asking myself why lisp and functional programming in general are not really taught in schools.
- pcmaffey 9y agoThis article fails to understand what components are in React. They are the building blocks for every aspect of an application. My data stores are components, my views are components, my styles are components. The author obviously comes from an MVC background where a component is one specific aspect of an application, and enabling it to do all these other things seems sacrosanct. But they've got it backwards. Think of a React component on the same level as a function: we design our functions as purely as we can, but it's not the function's fault if it's written poorly.
- jraines 9y agoI think it's more of an argument against such an understanding of a component, similar to the view that too much was packed into jQuery add-ons.
- divs1210 9y agoThe author also mentions why they see this property of React as a problem. This is just like earlier versions of Java which didnt have enums or lambdas, but used classes for everything. See what's happened now.
- lilactown 9y agoEDIT: I also think you've severely misinterpreted the article; re-frame (the library/framework that builds on top of reagent, which is a wrapper for React in clojurescript) is basically Redux's suave older brother IMO. [EDIT: Regarding "everything is a component"] And this is a weakness. If everything is a component, everything is tied to the React library/ecosystem. It would be better to treat everything as a primitive - like, say, a function. My data stores are functions (closures), my styles are functions that return data structures, my views are functions that return components. IMO the craze that struck a lot of the React ecosystem (everything's a component! State is a component! Routes are components! Side effects are components!) is dying down and people are realizing that it's better to stick to things that are much simpler and has first-class support from the language. Tying yourself to React (or any one technology) fundamentally limits your capabilities and expressiveness, and also makes your software very brittle. This is why, IMHO, most JavaScript devs actually would be much happier writing in Clojure(Script). The language provides first-class support for so many things that JS devs have to reach to libraries and frameworks for, e.g. immutability, CSP, pattern matching, and actual functional constructs like transducers.
- hashkb 9y agoMobx / rxjs solves a lot of these problems for those of us who can't use cljs or elm because our clients are afraid of them.