State
- re-renders the component when something changes
- should not be used for values that do not directly affect the UI
Refs
- do not cause a re-evaluation of the component when something changes.
- can be used to gain direct access to DOM elements (→ great for reading values or accessing certain browser APIs).
Example with “User Tic-Tac-Toe”
- Implementation with useState
//Player.jsx with state
export default function Player() {
const [playerName, setPlayerName] = useState(null);
const [submitted, setSubmitted] = useState(false);
function handleChange(event) {
setSubmitted(false);
setPlayerName(event.target.value);
}
function handleClick() {
setPlayerName(playerNameRef.current.value);
}
return (
<section id="player">
<h2>Welcome {submitted ? playerName : ' unknown entity'}</h2>
<p>
<input type="text" onChange={handleChange} value={playerName}/>
<button onClick={handleClick}>Set Name</button>
</p>
</section>
);
}
- Implementation with useRef
//Player.jsx with ref
import { useRef } from "react";
import { useState } from "react";
export default function Player() {
const playerNameRef = useRef();
const [playerName, setPlayerName] = useState(null);
function handleClick() {
setPlayerName(playerNameRef.current.value);
}
return (
<section id="player">
<h2>Welcome {playerName ?? 'unknown entity'}</h2>
<p>
<input type="text" ref={playerNameRef}/>
<button onClick={handleClick}>Set Name</button>
</p>
</section>
);
}
//App.jsx
import { useRef } from "react";
import Form from "./Form";
function App() {
const form = useRef();
function handleRestart() {
form.current.clear();
}
return (
<div id="app">
<button onClick={handleRestart}>Restart</button>
<Form ref={form}/>
</div>
);
}
export default App
//Form.jsx
import { forwardRef, useImperativeHandle, useRef } from "react";
const Form = forwardRef(function Form(props, ref) {
const form = useRef();
useImperativeHandle(ref, () => {
return {
clear() {
form.current.reset();
},
};
});
return (
<form ref={form}>
<p>
<label>Name</label>
<input type="text" />
</p>
<p>
<label>Email</label>
<input type="email" />
</p>
<p id="actions">
<button>Save</button>
</p>
</form>
);
});
export default Form;