How do I select certain bars in react.js?
This is my code:
var Progressbar = React.createClass({
getInitialState: function () {
return { completed: this.props.completed };
},
addPrecent: function (value) {
this.props.completed += value;
this.setState({ completed: this.props.completed });
},
render: function () {
var completed = this.props.completed;
if (completed < 0) { completed = 0 };
return (...);
}
I want to use this React component:
var App = React.createClass({
getInitialState: function () {
return { baction: 'Progress1' };
},
handleChange: function (e) {
var value = e.target.value;
console.log(value);
this.setState({ baction: value });
},
handleClick10: function (e) {
console.log('You clicked: ', this.state.baction);
document.getElementById(this.state.baction).addPrecent(10);
},
render: function () {
return (
<div class="center">Progress Bars Demo
<Progressbar completed={25} id="Progress1" />
<h2 class="center"></h2>
<Progressbar completed={50} id="Progress2" />
<h2 class="center"></h2>
<Progressbar completed={75} id="Progress3" />
<h2 class="center"></h2>
<span>
<select name='selectbar' id='selectbar' value={this.state.baction} onChange={this.handleChange}>
<option value="Progress1">#Progress1</option>
<option value="Progress2">#Progress2</option>
<option value="Progress3">#Progress3</option>
</select>
<input type="button" onClick={this.handleClick10} value="+10" />
<button>+25</button>
<button>-10</button>
<button>-25</button>
</span>
</div>
)
}
});
I want to execute the handleClick10 function and perform the operation for my selected progressbar. But the result I get is:
You clicked: Progress1
TypeError: document.getElementById(...) is null
How do I select the certain Element in react.js?
This question is related to
javascript
reactjs
getelementbyid
You can do that by specifying the ref
EDIT: In react v16.8.0 with function component, you can define a ref with useRef. Note that when you specify a ref on a function component, you need to use React.forwardRef on it to forward the ref to the DOM element of use useImperativeHandle
to to expose certain functions from within the function component
Ex:
const Child1 = React.forwardRef((props, ref) => {
return <div ref={ref}>Child1</div>
});
const Child2 = React.forwardRef((props, ref) => {
const handleClick= () =>{};
useImperativeHandle(ref,() => ({
handleClick
}))
return <div>Child2</div>
});
const App = () => {
const child1 = useRef(null);
const child2 = useRef(null);
return (
<>
<Child1 ref={child1} />
<Child1 ref={child1} />
</>
)
}
EDIT:
In React 16.3+, use React.createRef()
to create your ref:
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.myRef = React.createRef();
}
render() {
return <div ref={this.myRef} />;
}
}
In order to access the element, use:
const node = this.myRef.current;
DOC for using React.createRef()
EDIT
However facebook advises against it because string refs have some issues, are considered legacy, and are likely to be removed in one of the future releases.
From the docs:
Legacy API: String Refs
If you worked with React before, you might be familiar with an older API where the ref attribute is a string, like "textInput", and the DOM node is accessed as this.refs.textInput. We advise against it because string refs have some issues, are considered legacy, and are likely to be removed in one of the future releases. If you're currently using this.refs.textInput to access refs, we recommend the callback pattern instead.
A recommended way for React 16.2 and earlier is to use the callback pattern:
<Progressbar completed={25} id="Progress1" ref={(input) => {this.Progress[0] = input }}/>
<h2 class="center"></h2>
<Progressbar completed={50} id="Progress2" ref={(input) => {this.Progress[1] = input }}/>
<h2 class="center"></h2>
<Progressbar completed={75} id="Progress3" ref={(input) => {this.Progress[2] = input }}/>
Even older versions of react defined refs using string like below
<Progressbar completed={25} id="Progress1" ref="Progress1"/>
<h2 class="center"></h2>
<Progressbar completed={50} id="Progress2" ref="Progress2"/>
<h2 class="center"></h2>
<Progressbar completed={75} id="Progress3" ref="Progress3"/>
In order to get the element just do
var object = this.refs.Progress1;
Remember to use this
inside an arrow function block like:
print = () => {
var object = this.refs.Progress1;
}
and so on...
You can replace
document.getElementById(this.state.baction).addPrecent(10);
with
this.refs[this.state.baction].addPrecent(10);
<Progressbar completed={25} ref="Progress1" id="Progress1"/>
Disclaimer: While the top answer is probably a better solution, as a beginner it's a lot to take in when all you want is something very simple. This is intended as a more direct answer to your original question "How can I select certain elements in React"
I think the confusion in your question is because you have React components which you are being passed the id "Progress1", "Progress2" etc. I believe this is not setting the html attribute 'id', but the React component property. e.g.
class ProgressBar extends React.Component {
constructor(props) {
super(props)
this.state = {
id: this.props.id <--- ID set from <ProgressBar id="Progress1"/>
}
}
}
As mentioned in some of the answers above you absolutely can use document.querySelector
inside of your React app, but you have to be clear that it is selecting the html output of your components' render methods. So assuming your render output looks like this:
render () {
const id = this.state.id
return (<div id={"progress-bar-" + id}></div>)
}
Then you can elsewhere do a normal javascript querySelector call like this:
let element = document.querySelector('#progress-bar-Progress1')
put it your input field
ref={(el) => this.myInput = el}
For getting the element in react
you need to use ref
and inside the function you can use the ReactDOM.findDOMNode
method.
But what I like to do more is to call the ref right inside the event
<input type="text" ref={ref => this.myTextInput = ref} />
This is some good link to help you figure out.
Since React uses JSX code to create an HTML we cannot refer dom using regulation methods like documment.querySelector or getElementById.
Instead we can use React ref system to access and manipulate Dom as shown in below example:
constructor(props){
super(props);
this.imageRef = React.createRef(); // create react ref
}
componentDidMount(){
**console.log(this.imageRef)** // acessing the attributes of img tag when dom loads
}
render = (props) => {
const {urls,description} = this.props.image;
return (
<img
**ref = {this.imageRef} // assign the ref of img tag here**
src = {urls.regular}
alt = {description}
/>
);
}
}
Source: Stackoverflow.com