Error: The style
prop expects a mapping from style properties to values, not a string
위의 문제는 바로, {}괄호가 하나가 들어있었기 때문이다. style={color}의 문제이다. JSX에서 {}를 써서 JS를 표현한다. 그래서 아래의 코드로 바꾸어야 한다.
<div style={{color}} name={name}>Hello</div>
가장 밖의 {}는 JSX문법, 안의 {}객체 리터럴이다.
https://ko.reactjs.org/docs/jsx-in-depth.html
function App() {
return (
<Wrapper>
<Hello name="Mia" color="red" isSpecial={true} />
<Hello color="pink" isSpecial={false} />
</Wrapper>
);
}
function Hello({ name, color, isSpecial }) {
return (
<Fragment>
<div style={{ color }} name={name} >
{isSpecial ? <b>*</b> : null}
안녕하세요{name}</div>
</Fragment>
)
}
export default Hello;
isSpecial={false}로 쓴 것 또한 JS값을 주기때문이다.
과거의 리액트의 함수형 컴포넌트에서는 상태를 관리할 수 없었지만, 리액트 16.8에서 Hooks라는 기능이 도입되면서, 함수형 컴포넌트에서도 상태를 관리할 수 있다.
import React, { useState } from "react";
function Counter() {
const [number, setNumber] = useState(100);
const onIncrease = () => {
setNumber(number + 1);
}
const onDecrease = () => {
setNumber(number - 1);
}
return (
<div>
<h1>{number}</h1>
<button onClick={onIncrease}>+1</button>
<button onClick={onDecrease}>-1</button>
</div>
);
}
export default Counter;
리액트에서 이벤트를 설정해줄 때에는, on이벤트이름={실행할함수} 형태로 설정해주어야 한다. 단 onClick={onIncrease()}는 놉! ()는 즉시 실행해버리게 됨으로.
컴포넌트에서 동적인 값을 상태라고 한다. 리액트에는 useState는 이러한 동적인 동작의 대표적인 함수.
const [number, setNumber] = useState(100);
100은 초기값을 설정해주는 것이고, []이렇게 쓰여진 것은 비구조적 할당이다. number은 현재 상태, setNumber setter함수!
useState를 이용하여 변수를 선언하면 2개의 아이템 쌍이 들어있는 배열로 만들어집니다. 첫 번째 아이템은 현재 변수를 의미하고, 두 번째 아이템은 해당 변수를 갱신해주는 함수입니다.
배열 구조 분해라는 특별한 방법으로 변수를 선언해주었기 때문에 [0]이나 [1]로 배열에 접근하는 것은 좋지 않을 수 있습니다.
import React, { useState } from "react";
function Counter() {
const [number, setNumber] = useState(100);
const onIncrease = () => {
setNumber(prevNumber => prevNumber + 1);
}
const onDecrease = () => {
setNumber(prevNumber => prevNumber - 1);
}
return (
<div>
<h1>{number}</h1>
<button onClick={onIncrease}>+1</button>
<button onClick={onDecrease}>-1</button>
</div>
);
}
export default Counter;
setNumber(prevNumber => prevNumber - 1) 이런식으로 바꿔줄 수 있는데, 이거 map(item => item-1 ) 이랑 비슷한 구조. 즉 다음의 상태로 파라미터로 넣어준 것이 아니라, 값을 업데이트할 함수를 파라미터로 넣어준 것이다.
(prevNumber => prevNumber +1 ) 자체가 함수!
const [num, setNum ] = useState(0)
setNum은 무조건 함수인지, 그리고 prevNumber => prevNumber - 1 은 파라미터로 익명함수를 구현한 것인지.
=> 위의 질문의 공식문서에서 답을 찾을 수 있다.
state "변수”를 선언할 수 있습니다. 위에 선언한 변수는 num 라고 부르지만 banana처럼 아무 이름으로 지어도 됩니다. useState는 클래스 컴포넌트의 this.state가 제공하는 기능과 똑같습니다. 일반적으로 일반 변수는 함수가 끝날 때 사라지지만, state 변수는 React에 의해 사라지지 않습니다.
useState의 인자로 무엇을 넘겨주어야 할까요? useState() Hook의 인자로 넘겨주는 값은 state의 초기 값입니다. 함수 컴포넌트의 state는 클래스와 달리 객체일 필요는 없고, 숫자 타입과 문자 타입을 가질 수 있습니다. 위의 예시는 사용자가 버튼을 얼마나 많이 클릭했는지 알기를 원하므로 0을 해당 state의 초기 값으로 선언했습니다. (2개의 다른 변수를 저장하기를 원한다면 useState()를 두 번 호출해야 합니다.)
useState는 무엇을 반환할까요? state 변수, 해당 변수를 갱신할 수 있는 함수 이 두 가지 쌍을 반환합니다. 이것이 바로 const [num, setNum] = useState()라고 쓰는 이유입니다. 클래스 컴포넌트의 this.state.num와 this.setNum와 유사합니다.
num라고 부르는 state 변수를 선언하고 0으로 초기화합니다. React는 해당 변수를 리렌더링할 때 기억하고, 가장 최근에 갱신된 값을 제공합니다. num 변수의 값을 갱신하려면 setNum를 호출하면 됩니다.
https://ko.reactjs.org/docs/hooks-intro.html#motivation
1: import React, { useState } from 'react';
2:
3: function Example() {
4: const [count, setCount] = useState(0);
5:
6: return (
7: <div>
8: <p>You clicked {count} times</p>
9: <button onClick={() => setCount(count + 1)}>
10: Click me
11: </button>
12: </div>
13: );
14: }
첫 번째 줄: useState Hook을 React에서 가져옵니다.
네 번째 줄: useState Hook을 이용하면 state 변수와 해당 state를 갱신할 수 있는 함수가 만들어집니다. 또한, useState의 인자의 값으로 0을 넘겨주면 count 값을 0으로 초기화할 수 있습니다.
아홉 번째 줄: 사용자가 버튼 클릭을 하면 setConut 함수를 호출하여 state 변수를 갱신합니다. React는 새로운 count 변수를 Example 컴포넌트에 넘기며 해당 컴포넌트를 리렌더링합니다.
input 상태관리.
import React, { useState } from "react";
function InputSample() {
const [text, setText] = useState('');
const onChange = (e) => {
setText(e.target.value);
}
const onReset = () => {
setText('');
}
return (
<div>
<input onChange={onChange} value={text} />
<button onClick={onReset}>초기화</button>
<div>
<b>값 : {text} </b>
</div>
</div>
);
}
export default InputSample;
import React, { useState } from "react";
function InputSample() {
const [inputs, setInputs] = useState({
name: '',
nickname: ''
})
const { name, nickname } = inputs;
const onChange = (e) => {
const { value, name } = e.target;
setInputs({
...inputs,
[name]: value
});
};
const onReset = () => {
setInputs({
name: '',
nickname: '',
})
}
return (
<div>
<input name="name" placeholder="이름" onChange={onChange} value={name} />
<input name="nickname" placeholder="닉네입" onChange={onChange} value={nickname} />
<button onClick={onReset}>초기화</button>
<div>
<b>값 : </b>
{name} ({nickname})
</div>
</div>
);
}
export default InputSample;
코드를 뜯어보면,
const [inputs, setInputs] = useState({
name: '',
nickname: ''
})
상태의 값이 name과 nickname이 두개이다. 왜냐하면 변할 값이 name과 nickname임으로, useState({})에 넣어논 것.
const { name, nickname } = inputs;
name과 nickname 있는 inputs를 비할당구문으로 주입하고,
<div>
<input name="name" placeholder="이름" onChange={onChange} value={name} />
<input name="nickname" placeholder="닉네입" onChange={onChange} value={nickname} />
<button onClick={onReset}>초기화</button>
<div>
<b>값 : </b>
{name} ({nickname})
</div>
</div>
input태그안에 name 속성과 value 속성을 갖고 있고, 값은 "name" value={name} 으로 되어있다. 현재 첫 value값은 ''이다. onChange 이벤트가 일어나면, onChange 함수로 가는데,
const onChange = (e) => {
const { value, name } = e.target;
setInputs({
...inputs,
[name]: value
});
};
이벤트의 target값 중 value와 name의 key를 갖고 있는 값을 주입한다. 그리고 setInputs를 이용하여, spread 기능을 이용하여 기존의 inputs 값을 복사하여, name을 키로 갖고 있는 곳에 value값으로 상태를 변경해 준다.
리액트에서 상태를 수정할때는 state값을 직접적으로 바꾸어주면 안된다. 새로운 객체를 만들고, 새로운 객체에 값을 주어야 한다. 이러한 작업을 불변성을 지킨다고 한다.
리액트에서 DOM을 사용해야 할 경우에 사용하는 Hook. 포커스를 주거나 할때!
import React, { useRef, useState } from "react";
function InputSample() {
const [inputs, setInputs] = useState({
name: '',
nickname: ''
})
const nameInput = useRef();
const { name, nickname } = inputs;
const onChange = (e) => {
const { value, name } = e.target;
setInputs({
...inputs,
[name]: value
});
};
const onReset = () => {
setInputs({
name: '',
nickname: '',
});
** nameInput.current.focus();**
}
return (
<div>
<input name="name" placeholder="이름" onChange={onChange} value={name} ref={nameInput} />
<input name="nickname" placeholder="닉네입" onChange={onChange} value={nickname} />
<button onClick={onReset}>초기화</button>
<div>
<b>값 : </b>
{name} ({nickname})
</div>
</div>
);
}
export default InputSample;