Measuring the absolute position of a series of DOM elements in React - javascript

Sandbox: https://codesandbox.io/s/8292lmypz2
I'm trying to measure the absolute position some divs. I'm accessing the DOM node of the div through a forwarded ref (React.forwardRef()) to the div I'm interested in. In the constructor of my parent component, I'm populating an array with React.createRef()s, which I then assign to each divs ref iteratively as they're being rendered. Finally, I log the return value of getBoundingClientRect() for each div. The problem is that - in spite of the fact that each div has a unique position relative to the next one - the same data is returned every single time. It's as if I was getting the getBoundingClientRect() data for the same div eight times. What gives?

A very basic issue in your case is that in order to create the array of refs, you are using Array.fill method, which initialises all the values in the array with the same reference of the React.createRef, and hence when you try assign refs to the divs, all ref properties will refer to the last div being assigned the ref instance
A simple way to fix this is to use Map instead of fill like
constructor(props) {
super(props);
this.refArray = Array.apply(null, { length: props.number.length}).map(() => React.createRef());
}
Working demo

Related

Svelte: Trigger update of {#each} in child component [duplicate]

This question already has answers here:
Svelte's reactivity with array operation
(2 answers)
Closed 6 months ago.
I am trying to update a child component with an {#each} loop inside it to add additional items by push()ing them to the array that is iterated by the child component. While an individual variable (say a string or number) works fine and array that feeds a {#each} loop doesn't seem to.
I am using a bind: to pass live data to the child component and have also tried to use a $: array statement in the child. Whatever I do, pushing new data to the array in the parent has no effect on the child, is there a way to do this or do I have to split off and re-render the whole child component {#each} loop every time?
I have posted my test script in a REPL: https://svelte.dev/repl/e1f24f8fccfa4533a1d682d163af9a66?version=3.49.0
Type text in to the input box and hit the 'Note This' button.
If you watch the JS Console you can see the array expanding, but the {#each} loop is not rendering the extra items to the child component.
Svelte works in a way where it only detects updates from assignment. You can read more about it here:
https://svelte.dev/docs#component-format-script-2-assignments-are-reactive.
Using methods such as push won't automatically trigger updates.
In your case you can just add testData = testData after pushing the new object and it works fine.

React. Store JSX class component and change it's props later

Im developing a react image editor, and I want to draw lines on the canvas, to do this I have a class that i add to the canvas elements array (this stores all the diferent elements, text, images and lines that the canvas redraws every frame).
But when i do this:
let pos = this.stageRef.current.getPointerPosition()
let new_line = (<Line
key={this.state.itemArray.length}
stroke={'#df4b26'}
strokeWidth={5}
globalCompositeOperation={'source-over'}
points={[pos.x, pos.y]}
/>)
this.state.itemArray.push(new_line)
this.setState({isDrawing: true})
console.log(new_line)
I get this object:
This object it's located inside the itemsArray, all the items are rendered on the main render here:
And it's rendered correctly, but all it's props are read-only and i can't call any methods of the object, what i need it's the "real" React object, the one you get when you call a reference.
(I want to add more points to the line object onMoveMouse event)
this:
Is there any way I can get the Line object (i just created) accesing to the itemsArray object instead of using the ref?
I don't know how can i create a Line object directly and call it's methods without a Ref ¿Do I really need a ref to an object i just created 2 lines above?.

Dynamic refs inside v-for loop giving error don't appear in DOM. **Provided element is not within a Document**

I am using canvas2Html where you i pass the ref of element to take image of element. i am dynamically assigning the refs to take image of particular divs. The code runs but i am getting the Provided element is not within a Document. In Devconsole refs are not appearing too.
I am really stuck on this one. Any suggestions
https://codesandbox.io/embed/rlo3mmo5zp?fontsize=14
I want the image of signature and initial as output. I am currently getting error. :/
Do not forget that if you use :ref inside v-for then it becomes an Array - so you should change your code
async takeimage(name) {
let el = this.$refs[name][0]; // <--- use an Array

React - get React component from a child DOM element?

I'd like to be able to figure out what React component is associated with a certain DOM element.
For example, say I have a div, and I'm rendering my entire application using React. The div has to be rendered by a React component - but which one?
I know that React supplies the method "getDOMNode" to get the DOM node associated with a React component, but I'd like to do the opposite.
Is this possible?
No.
A central concept in React is that you don't actually have a control in the DOM. Instead, your control is that factory function. What's in the DOM is the current render of the control.
If you actually need this, you can keep an object as a global variable, whose keys are the string representations of the names of factory functions, and whose values are the factory functions, then on your renderable div, keep an attribute containing the name of the factory function.
But chances are this is a question of the XY problem (needing X, seeing a way with Y, then asking how to do Y.) Probably if you'd explain your goal there's a better way that better fits React's top-down conceptual model.
Generally speaking, asking to get access to the control from its render is like asking to get access to an SVG from its cached PNG render. It's possible, but it's usually a red flag that something else is conceptually wrong.
Here's what I use, with React 15.3.0:
window.FindReact = function(dom) {
for (var key in dom) {
if (key.startsWith("__reactInternalInstance$")) {
var compInternals = dom[key]._currentElement;
var compWrapper = compInternals._owner;
var comp = compWrapper._instance;
return comp;
}
}
return null;
};
And then to use it:
var someElement = document.getElementById("someElement");
FindReact(someElement).setState({test1: test2});
If your situtation demands getting react element from DOM node, here is an approach, "Communicate via event and call back"
You shall fire a custom event on DOM element and have event listener for that custom event in React component. This will map DOM element back to react component.

knockout.js referring to parent object

I have a complex knockout.js object which is effectively an observableArray with another observableArray inside. I have a remove function which asynchronously removes chosen element from the second array. An item is being archived in the database, while one of its observable properties on client side is being set to false making it to disappear from the screen.
A remove button event is created using $root keyword:
Remove
What gives me access to details of the chosen element using "this" keyword. My problem is, that while deleting item from the second array I would like to change something to its parent item in the first array. As I mentioned "this" keyword refers to the child item, is there any way I could access the parent item at the same time as well?
mhu's answer is a antipattern because it creates a dependency between ViewModel and the structure of the View.
Instead do
Remove
Parent Viewmodel
removeActivity: function(activity) {
this.activities.remove(activity);
}

Categories