We are trying to figure out cause of following issue from styled-components project: https://github.com/styled-components/styled-components/issues/389
There were some changes made to refs + setNativeProps that broke animation in one place, assumingly because some animated related information is not being passed down correctly.
Hence the question to understand how createAnimatedComponent alters initial component, whats added? What could cause animation to break if not passed down correctly?
Please provide ideas / detailed answer if you know what could be causing this issue.
UPDATE
Breaking change related to the issue occurred somewhere within this file for reference innerRef passes down ref, isTag function checks if it is a native component.
animatable components can be animated. View, Text, and Image are already provided, and you can create custom ones with createAnimatedComponent. These special components do the magic of binding the animated values to the properties, and do targeted native updates to avoid the cost of the react render and reconciliation process on every frame. They also handle cleanup on unmount so they are safe by default.
https://facebook.github.io/react-native/docs/animated.html
Related
I'm creating a music app that loops through a one-bar sequence and triggers notes which lie in the sequence. I'd like to have a function in a component which triggers at regular intervals (say every 10ms) using setInterval() and changes the props of the child component to tell it how far through the sequence it is. This child component, or perhaps its own child, would then trigger the notes at the appropriate times (based on the current progress through the sequence, which it gets from the props updates, and the position of the notes).
I'm aware that React updates state (and props?) asynchronously, and so my question is: would updating props in this way be quick, consistent and reliable enough to keep a steady beat and trigger the notes in the appropriate places? If not, is there another method I could use within React or a different library altogether?
Please do let me know if you need any clarification.
I understand that you should not manually manipulate the DOM nodes rendered by a Vue component for reasons including:
After another render, Vue can override any changes you did
It can interfere with Vue's patching algorithm
My use case is I would like to implement a way to move a DOM node to a separately-controlled location for the purpose of displaying it fullscreen. Imagine an editor widget with a fullscreen button that "pops out" the editor and overlays it fullscreen.
I understand that I can achieve this with CSS alone using fixed positioning, but I'm not interested in that, I'm particularly interested in the consequences of moving the DOM node out from wherever it is and appending it directly to the <body> element. Will Vue still be able to patch the nodes correctly after the parent component re-renders?
I have experimented with this already and I have a working implementation, and I haven't encountered any issues yet. Still, this doesn't ease my concern, and the Vue docs don't talk about doing something like this.
What potential issues, if any, might I encounter?
portal-vue is unsuitable because it recreates the component instance each time it is relocated, which I do not want.
Depending on how the component lifecycle works in Vue, moving a component in the DOM might trigger lifecycle methods. E.g. with Custom Elements, moving means triggering disconnectedCallback of the component, and subsequently connectedCallback. This is often where the component initialization takes place.
Rather than moving the component manually from the outside, consider giving the component itself the ability to relocate.
I am facing a really nasty issue, I need to create a badge component that it'll be places over a custom component.
This is my first attempt to create something similar in React, with HTML is way easier because you work directly with the DOM.
In this case instead I need to create a badge that will highlight a new component/feature, when you click on it a popup get's open with a bit of text that'll explains what the component is about, aka it's functionality. Telling you this because I need to listen for onClick and it's not possible to use pseudo-elements.
The base idea
<BadgeComponent position="top left">
<CustomComponent />
</BadgeComponent>
Since I can't use a pseudo-element that'll inherit all the element CSS properties this is my thinking:
do not change the CustomComponent because each time could be different
the BadgeComponent is a wrapper that creates a div with position:relative (so I can position the badge wherever I want)
BadgeComponent needs to be display: inline-block otherwise it'll change the overall layout
I need to take the CustomComponent box-model properties, remove from it and apply them to the BadgeComponent. This mostly because margins are messing with the BadgeComponent size and position the badge itself will be trickyer
Basically I need to take the CSS properties of the DOM element rendered from the child component.
The approach
So I've been experimenting with some code before came here and my first attempt has been to dinamically pass a ref to the child component of BadgeComponent with this snippet:
{React.Children.map(this.props.children, (element, idx) => {
if (idx > 0) return; // don't care if it has more childrens, at least for now.
return React.cloneElement(element, { ref: this.newFeature });
})}
I also thought to take the CustomComponent as a prop of BadgeComponent, like so:
<BadgeComponent position="top left" target={ CustomComponent }>
But I didn't (yet) followed this path because I thought that at the end of the day this.props.target it's basically the same of this.props.children and didn't earn anything doing so. Am I right?
I know that in React we have ref to get a reference to the DOM created from a component but in this case is not applicable because I am not applying the ref to the component that renders an HTML, I am applying it to CustomComponent that gets cloned and it doesn't pass to the DOM.
From my experiment everything works fine if I pass an HTML element, in the experimental code I have a div.box that gets the badge in the position that I want but as soon as I pass the Button I got the following error: Window.getComputedStyle: Argument 1 does not implement interface Element.
I am using window.getComputedStyle to get the CSS properties I care about.
My research
I've been looking all around the web and I've seen a nice implementation that, unfortunately, just works with styled components or styled defined inline in <style>. I am looking to not use NPM packages as this one because firstly I believe that it is possible to implement without reach for an additional package and second actually I do not like much the way that the sticky/badge get's implemented (with all respect obviously).
I don't know where to look anymore, I am not an expert JS/React developer (been WP theme developer for 10 years) so probably there is some basic concept that I missunderstand?
I've read about findDOMNode (looks will be deprecated soon) and forwardRef in the React ecosystem but I do not think that's the way to go, am I wrong?
I do not want the copy/paste code, well if you're so gentle to fork the codesandbox and share the solution will be great but I am trying to learn here: there is a way to get a reference of the rendered HTML element from any component?
Thinking that this is the missing part, if I can reach the DOM my code is already working 😊
I need to know component's width in render method, but getting DOM elements in render method is not possible.
Solving problem I found this article. The problem in article is the same as mine.
Solution:
save component's width to state in componentDidMount method.
subscribe to window resize event and update state.
So I can get component width from component's state.
Anybody knows another approach to solve this problem?
Thanks.
Well, you don't have to save the width in state, you could grab it each time with ReactDOM.findDOMNode(), but this is about the best you're going to get. You can't update in render for two reasons:
your DOM elements are currently being rendered but don't exist yet
Even if they did, triggering an update in render is an easy way to trigger an infinite render loop.
Tldr: Just go with the method you have, that works just fine
Suppose we have two sibling react components called OldContainer and NewContainer. There is a child component inside OldContainer that contains a <video> tag, and the video is currently playing.
The user can now drag the child component (with the video) and drop it in the NewContainer, and they expect the video to keep playing while it's being dragged and after being dropped.
So the video appears to stick to the mouse position, and when dragged and dropped in the new container, it animates to its new position (again, it doesn't get paused).
How would you implement this? Can we implement this in a pure way (in line with the spirit of pure functions)?
Clarification: I could have used some other element instead of a video tag for explaining this problem. A NumberEasing element would be a better example, since it would require the props and state of the component to be preserved during and after the interaction.
Update 1: Code examples obviously would be nice, but what I'm mainly looking for is just a general description of how you would approach this problem in a "functional" way. How do you keep your view code simple and easy to reason about? Who handles the drag-and-drop gesture? How do you model the data that's fed into the views?
Take a look at this library : react-reverse-portal
What is it that you want to preserve? Is it Javascript objects that the component holds as state, or is it state in the DOM (like how long a video has played, or text selection in an input box)?
If it's just Javascript objects as state, you're better of moving the source of that state to another service (something like Flux). That way, it doesn't matter if the component gets recreated because it can be recreated with the state that was there before.
EDIT
The way to keep your view code simple and easy to reason about is to not keep state inside your components. Instead, all data that the component needs should be passed into the component as props. That way, the component is "pure" in that it renders the same output given the same props. That also makes the problem of wanting to reuse a component instance a non-issue, since it doesn't matter when the same input gives the same output.
For drag and drop, I'd suggest looking at: https://github.com/gaearon/react-dnd.
How you model the data you pass to view components is up to you and the needs of your application. The components shouldn't care, they should just expect to get data passed as props, and to render them. But the popular approach to dealing with this is of course Flux, and there are many libraries that implements Flux in different ways.
SECOND EDIT
Regarding if you have a subtree with hundreds of components that you want to move: I'd still start off by making the state external (pure components), and render that tree in a new place. That means that React will probably recreate that entire subtree, which is fine. I wouldn't deviate from that path unless the performance of it turned out to be horrible (just guessing that it might be horrible isn't enough).
If the performance turned out to be horrible, I would wrap that entire subtree in a component that caches the actual DOM tree and reuses it (if it gets passed the same props). But you should only do this when absolutely needed, since it goes against what React tries to do for you.
THIRD EDIT
About gestures: I'd start out with listening to gesture events in componentDidMount, and in the event callback call setState on the component with the coordinates it should have. And then render the component in render with the coordinates given. React won't recreate the component when you call setState but it will re-render it (and diff the output). If the only thing you changed was the coordinates, it should render fast enough.
If that turns out to be too slow, like if the subtree of that component is huge and it becomes a bottleneck to recreate the subtree of vDOM, I'd reposition the DOM node directly in a RAF-loop outside of Reacts control. And I'd also put a huge comment on why that was needed, because it might seem wierd for some other developer later.
Create a new variable using const or var. Put the instance of data using rest spread operator, update the necessary data to pass and send the data to the component without mutating the state of component.
Just like:
const data = {
...this.state.child,
new_data : 'abc'
}