'How to access/override the className of an element using refs?
I have a text and a button.
What I want to achieve is something like this, that if I clicked the Button the Text will be hidden. I want to achieve this without using state.
class Test extends Component {
constructor(props){
//codes
}
hide = () => {
const span = this.refs.spanLoading;
span.ClassName = "hidden";
}
render() {
return (
<span ref="spanLoading" id="test-id" className="">The Quick Brown Fox.</span>
<button onClick={() => this.hide()}>Hide</button>
);
}
}
export default Test;
Solution 1:[1]
You can use useRef() hook.
Maintain one ref object which is not a string.
const {useRef} = React;
function App() {
const ref = useRef(null);
const onClick = () => {
const span = ref.current; // corresponding DOM node
span.className = "hidden";
};
return (
<div>
<span ref={ref} className="">The Quick Brown Fox.</span>
<button onClick={onClick}>Hide</button>
</div>
);
}
ReactDOM.render(
<App />,
document.getElementById("root")
);
.hidden {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="root"></div>
Solution 2:[2]
This can be achieved simply, your approach is correct just some few fixes.
- You can return only one element in JSX
- The ref should be maintained somewhere in JS memory
Check this code and the working codesandbox instance here
class Test extends React.Component {
constructor() {
super();
this.inputRef = React.createRef();
}
hide = () => {
console.log(this.inputRef);
this.inputRef.current.style.visibility="hidden";
};
render() {
return (
<>
<span ref={this.inputRef} id="test-id" className="">
The Quick Brown Fox.
</span>
<button onClick={() => this.hide()}>Hide</button>
</>
);
}
}
EDIT! As you asked about dynamically generated refs...
This is what I understood as your requirement... see whether it matches it.
Working sandbox here
class Test extends React.Component {
constructor() {
super();
this.inputRef = React.createRef();
this.refCollection = {};
for (let id = 0; id < 10; id++) {
this.refCollection["id_" + id] = React.createRef();
}
}
hide = e => {
console.log(this.inputRef);
this.inputRef.current.style.visibility = "hidden";
};
hideInCollection = k => {
let changedRef = this.refCollection[k];
changedRef.current.style.visibility = "hidden";
};
render() {
return (
<>
<span ref={this.inputRef} id="test-id" className="">
The Quick Brown Fox.
</span>
<button onClick={() => this.hide()}>Hide</button>
{Object.keys(this.refCollection).map(k => (
<div>
<span ref={this.refCollection[k]} id="test-id" className="">
Looped the Quick Brown Fox
</span>
<button onClick={() => this.hideInCollection(k)}>Hide</button>
</div>
))}
</>
);
}
}
Solution 3:[3]
class Test extends Component {
constructor(props){
this.hide = this.hide.bind(this);
}
hide() {
this.span.classList.add("hidden");
}
render() {
return (
<div>
<span ref={(el) => { this.span = el; }} id="test-id" className="">The Quick Brown Fox.</span>
<button onClick={this.hide}>Hide</button>
</div>
);
}
}
export default Test;
You should return a single element tho
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | |
| Solution 3 | joseluismurillorios |
