Los ... (o tres puntos) son conocidos como spread syntax y lo que permite es pasar todos los valores de un array o string sin tener que escribir cada uno, es útil cuando no se saben exactamente cuantos parámetros van a llegar.
handleChange = e => {
this.setState({
form: {
...this.state.form,
[e.target.name]: e.target.value,
},
});
};
Equivalente a los ... es slice
const squares = current.squares.slice();
Y podemos concatenar con concat
this.setState({
history: history.concat([{
squares: squares,
}]),
xIsNext: !this.state.xIsNext,
});