🦄
React.jsの謎仕様
親コンポーネントが子コンポーネントから値を受け取る際、
関数コンポーネントであれば
const Parent: React.FC<{}> = () => {
const [text, setText] = useState("");
// ↑親コンポーネントで使う:textの初期値とtextを更新する関数を宣言
// ↓子コンポーネントから受け取った値で親コンポーネントのtextを更新する関数
const handleValueChange = (newValue: string) => {
setText(newValue);
};
return (
<div>
<Child count={1000} handleValueChange={handleValueChange} />
<Child2 text={text} />
</div>
);
}
type ChildProps2 = {
text: string;
}
const Child2: React.FC<ChildProps2> = props => { // 引数でpropsを受け取る
return (
<>
<p className='text'>{props.text}</p>
</>
)
}
type ChildProps = {
count: number;
handleValueChange: (val: any) => void
}
const Child: React.FC<ChildProps> = props => { // 引数でpropsを受け取る
const handleInputChange = (event: any) => {
const value = event.target.value;
props.handleValueChange(value);
}
return (
<>
<input type="text" onChange={handleInputChange} />
<p>{props.count}</p>
</>
)
}
と記述することで、子コンポーネントにある関数を上書きしたり、子コンポーネントのpropsの値を更新することができる。
しかし、クラスコンポーネントにリファクタリングした場合
type Parent2State={
text:string;
}
//こっちはダメ?
class Parent2 extends React.Component<{}, Parent2State>{
constructor(props:{}){
super(props);
this.state={text:""};
}
handleValueChange(newValue: string){
this.setState({text:newValue});
};
render() {
return (
<div>
<Child count={1000} handleValueChange={this.handleValueChange} />
<Child2 text={this.state.text} />
</div>
);
}
}
//子コンポーネントは以下略
とすると、エディタ上では特に問題ないが子コンポーネントでinputタグの値を変えると
TypeError: this.setState is not a function
と出てsetStateが既存関数として扱われない?と思われる。
しかし少し記述を変えて
type Parent2State={
text:string;
}
class Parent2 extends React.Component<{}, Parent2State>{
constructor(props:{}){
super(props);
this.state={text:""};
}
handleValueChange(newValue: string){
this.setState({text:newValue});
};
render() {
return (
<div>
{/*関数の宣言方法を変更した */}
<Child count={1000} handleValueChange={(e:string)=>this.handleValueChange(e)} />
<Child2 text={this.state.text} />
</div>
);
}
}
というようにhandleValueChange={(e:string)=>this.handleValueChange(e)}とすることで、実行しても特に問題なくなる。
Discussion
失礼します
この挙動は React に固有のものではなく、JS の(アロー関数でない書き方の)関数における this の仕様によるものです
コメントありがとうございます!
bindしない場合、クラスの中ではthisの指すものが変わってしまうんですね。
リンク付きでありがとうございます