I'm new in React, but I have some experience in JS.
My question is:
I have a function and I put this functions to onMouseOver event to element
<td> in current situation.
I want to get this current dom element and get index of this element next.
My code is bellow:
var Cell = function(k) {
function getIndex(cell){
console.log(cell)
}
return (
<td key ={k} onMouseOver={function() {getIndex(this)}}>
<div className="square__cell" ></div>
</td>
)
}
In js it works something like this. But now in React it returns me null.
If I put in console.log "1" for example it also works. So function is woks and I have only problem to get information about current element
Please help to find out how to do it.
Thanks.
You have to bind the function instead of creating new function so the context scope of component remains same
var Cell = function(k) {
function getIndex(cell){
console.log(cell)
}
return (
<td key ={k} onMouseOver={this.getIndex.bind(this,k)}}>
<div className="square__cell" ></div>
</td>
)
}
Related
I am generating some div's and appending to the DOM with this function
//Run forEach method on newObj(cats from local storage) to populate and append template to the DOM
function getTheCats() {
//Limiting the results to 3. Probably better way to do this.
newObj.slice(0, 3).forEach(cat => {
const catEl = document.createElement('div')
catEl.classList.add('cat-detail')
catEl.innerHTML = `
<div class="img-id-container" id="pointer-control" onclick="getCatDeets()">
<img class='cat-image' src='${cat.thumbnail_url}' alt="Cat Pic"/>
<h3 class="id-left">Cat ${cat.id}</h3>
</div>
<p class="birthday-left">${cat.birthdate}</p>
`
mainLeft.appendChild(catEl)
})
}
getTheCats()
I am trying to log to console, some of the innerHTML when I click on one of the results.
I always get 'undefined' as a result. I know I am missing something, but I can't seem to figure out what. Any help would be greatly appreciated.
function myFunction(event) {
const clickedCat = event.target.nodeName;
console.log(clickedCat);
const details = clickedCat.innerHTML
console.log(details)
}
From David784 in the comments,
I unnecessarily added .nodeName to event.target
I replaced it with .innerHTML and I am able to retrieve the data I need.
function myFunction(event) {
const clickedCat = event.target.innerHTML;
console.log(clickedCat);
const details = clickedCat.innerHTML
console.log(details)
}
I am creating a geography game where you are supposed to click on a specific country on a world map - if you click on the right one, the country changes color and the game presents a new country to be clicked at. If the player doesn't know, he can click on a button which will show him the correct answer. For this, I want to simulate a click event, so that the same onClick() function is called as if you clicked on the correct country.
I am using D3, and the world map is made up of svg paths. Below is the code I thought would work, using the HTMLElement.click() method:
function simulateClick() {
// for each index in the nodelist,
// if the properties are equal to the properties of currentTargetUnit,
// simulate a click on the path of that node
let nodelist = d3.selectAll(".unit")
for (let i = 0; i < nodelist._groups[0].length; i++) {
if (nodelist._groups[0].item(i).__data__.properties.filename === currentTargetUnit.properties.filename) {
console.log(nodelist._groups[0][i])
// logs the correct svg path element
nodelist._groups[0][i].click()
// logs TypeError: nodelist._groups[0][i].click is not a function
}
}
}
I then looked at some tutorials which say that, for some reason I don't fully understand, you rather need to use React.useRef for this - but in all their examples, they put a "ref" value on an element which is returned from the beginning in the React component, like so:
import React, { useRef } from "react";
const CustomTextInput = () => {
const textInput = useRef();
focusTextInput = () => textInput.current.focus();
return (
<>
<input type="text" ref={textInput} />
<button onClick={focusTextInput}>Focus the text input</button>
</>
);
}
This obviously doesn't work because my svg path elements aren't returned initially. So my question is - how can I achieve this, whether using useRef or not?
Below are some previous questions I looked at which also did not help.
Simulate click event on react element
React Test Renderer Simulating Clicks on Elements
Simulating click on react element
I finally solved it - instead of calling the onClick() which was set inside the node I created a new clickevent with the help of the following code:
function simulateClick() {
let nodelist = d3.selectAll(".unit")
for (let i = 0; i < nodelist._groups[0].length; i++) {
if (nodelist._groups[0].item(i).__data__.properties.filename === currentTargetUnit.properties.filename) {
var event = document.createEvent("SVGEvents");
event.initEvent("click",true,true);
nodelist._groups[0].item(i).dispatchEvent(event);
}
}
}
I'm using Rivets.js to draw some components within an rv-each-* block
They all render fine when the page loads.
When I Splice the first element of the model, the model correctly removes the first element but the rv-each-* block removes the last element.
The component is just made up of a button that contains the text of the objects value it is bound to. Next to each component call I print some text that is also bound to each objects value. The two should be the same, but after the Splice they are not.
var model2 = [{ "value":"1"},{"value":"2"},{"value":"3"}];
rivets.components['control'] = {
template: function() {
return '<button>{data.option.value}</button>';
},
initialize: function(el, attributes) {
return new controlviewmodel(attributes);
}
};
function doSplice()
{
model2.splice(0,1);
}
<table id="view">
<tr rv-each-option="model">
<td>
<control option="option"/>
</td>
<td>{option.value}</td>
</tr>
</table>
I've created a fiddle to try and show my problem: http://jsfiddle.net/dko9b9k4/
Am I doing something wrong or is this a bug?
Edit: this example can be fixed by changing
return new controlviewmodel(attributes);
to return attributes;
I am getting this error while dynamically rendering a component in react
findComponentRoot(..., .0.1.1.0.1.0.5.0.1:4): Unable to find element.
This probably means the DOM was unexpectedly mutated (e.g., by the
browser), usually due to forgetting a when using tables,
nesting tags like <form>, <p>, or <a>, or using non-SVG elements in an
<svg> parent. Try inspecting the child nodes of the element with React
ID
I have checked out the markup and it seems fine. Sometimes the error changes on element, I mean, sometimes it appears to affect a certain element sometimes it appears on other elements.
Here is my render object:
render: function(){
var _slots = function(id, h, handleClick){
//react way to do this
var daysforSlot = this.props.workingDays.map(function(day, i){
var spanActive = this.state.appointments.map(function(appointment){
var _activeClass = null;
var _s = null;
if(h.hour+day === appointment.hour+appointment.day){
_activeClass = 'active'
}
if(_activeClass){
_s = <span className='active'>{appointment.patient.name}</span>
}
return ( {_s} )
});
return (
<td id={h.hour+day} onClick={handleClick.bind(null, {hour: h.hour, day:i})}>
{spanActive}
</td>
)
}.bind(this));
return(
<div>
<td>{h.text}</td>
<span>{daysforSlot}</span>
</div>
)
}.bind(this);
//creates the working hours for the days and bind the click
//handler to the hour slots
var _schedule = this.props.workingHours.map(function(h, i){
return (
<tr>
<span>{_slots(i, h, this.handleClick)}</span>
</tr>
)
}.bind(this));
return(
<span>
{_schedule}
</span>
)
}
Thanks in advance for any comments.
The html you're outputting is invalid. You have a td directly inside of a div - they must be the direct child of tr. Also you have a span as the child of tr, which is not valid.
I'm trying to implement a form where I can delete specific inputs using React. The problem is, react doesn't seem to be rendering the information correctly. This is my render function:
render: function(){
var inputItems;
if (this.state.inputs){
inputItems = this.state.inputs.map(function(input){
console.log(input)
return (
<Input
input={input}
onDestroy={this.destroy.bind(this, input)}
onEdit={this.edit.bind(this, input)}
editing={this.state.editing === input.id}
onCancel={this.cancel} />
);
}, this);
}
(...)
// this isn't the actual render return
return {inputItems}
and my destroy function:
destroy: function (input) {
var newInputs = this.state.inputs.filter(function (candidate) {
return candidate.id !== input.id;
});
this.setState({
inputs: newInputs
});
},
The actual destroy function is getting called through a child component via <a href="#" onClick={this.props.onDestroy}>(Remove)</a>. The interesting thing is that when I console log my inputs, as seen in the render function, the correct inputs are shown - the one I called the destroy function on is gone. But the incorrect inputs are rendered - it's always the very last one that disappears, not the one I called the destroy function on. So for example, I'll initially log:
First Name
Last Name
Email
and call the destroy function on the Last Name. The console.log will show:
First Name
Email
but the actual rendered information will show:
First Name
Last Name
Thanks!
Figured it out. Has to do with React child reconciliation. Added a key={input.id} to the <Input> tag and it works.
More information here under child reconciliation and dynamic children.
http://facebook.github.io/react/docs/multiple-components.html