![](/img/trans.png)
[英]How test callback click in child component that was passed from parent component?
[英]How is an argument for a callback in React being passed from the child component to the parent component?
我一直在使用https://reactjs.org/tutorial/tutorial.html上的React教程,我正在通过它。 我有一件事我无法绕过头脑。 这是完整的代码(codepen: https ://codepen.io/gaearon/pen/EmmOqJ ? edit = 0010):
function Square(props) {
return (
<button className="square"
onClick={props.onClick}>
{props.value}
</button>
);
}
function calculateWinner(squares) {
const lines = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
[0, 4, 8],
[2, 4, 6],
];
for (let i = 0; i < lines.length; i++) {
const [a, b, c] = lines[i];
if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
return squares[a];
}
}
return null;
}
class Board extends React.Component {
renderSquare(i) {
return (
<Square value={this.props.squares[i]} onClick={() => this.props.onClick(i)}/>
);
}
render() {
return (
<div>
<div className="status">{status}</div>
<div className="board-row">
{this.renderSquare(0)}
{this.renderSquare(1)}
{this.renderSquare(2)}
</div>
<div className="board-row">
{this.renderSquare(3)}
{this.renderSquare(4)}
{this.renderSquare(5)}
</div>
<div className="board-row">
{this.renderSquare(6)}
{this.renderSquare(7)}
{this.renderSquare(8)}
</div>
</div>
);
}
}
class Game extends React.Component {
constructor(props) {
super(props);
this.state = {
history: [{
squares: Array(9).fill(null),
}],
xIsNext: true,
};
}
handleClick(i) {
const history = this.state.history;
const current = history[history.length - 1];
const squares = current.squares.slice();
if (calculateWinner(squares) || squares[i]) {
return;
}
squares[i] = this.state.xIsNext ? 'X' : 'O';
this.setState({
history: history.concat([{
squares: squares,
}]),
xIsNext: !this.state.xIsNext,
});
}
render() {
const history = this.state.history;
const current = history[history.length - 1];
const winner = calculateWinner(current.squares);
let status;
if (winner) {
status = 'Winner: ' + winner;
} else {
status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O');
}
return (
<div className="game">
<div className="game-board">
<Board
squares={current.squares}
onClick={(i) => this.handleClick(i)}
/>
</div>
<div className="game-info">
<div>{status}</div>
<ol>{/* TODO */}</ol>
</div>
</div>
);
}
}
// ========================================
ReactDOM.render(
<Game />,
document.getElementById('root')
);
在本教程中,他们将回调函数handleClick(i)
从父Game
组件传递到子Board
组件,并从那里传递给子Square
组件。 我的问题是如何为参数i
设置? 我的猜测是起点是在Board
组件中调用renderSquare(i)
时候。 从那里我迷失了i
如何处理handleClick(i)
。 它存储在'onClick function object passed to
Square from
Board`中吗?
我的猜测是起点是在Board组件中调用renderSquare(i)的时候。 从那里我迷失了我如何处理点击(i)
你走在正确的轨道上。
在Board.render()
,使用数字1~8
调用this.renderSquare(...)
。
renderSquare
有一个onClick
处理程序, this.props.onClick(i)
。
renderSquare(i) {
return (
<Square value={this.props.squares[i]} onClick={() => this.props.onClick(i)}/>
);
}
this.props
从父, Game.render()
传递。
所以this.props.onClick
来自<Board onClick={...} />
class Game extends React.Component {
handleClick(i) {
...
}
render() {
...
return (
<div className="game">
<div className="game-board">
<Board
squares={current.squares}
onClick={(i) => this.handleClick(i)}
/>
</div>
...
</div>
);
}
}
所以this.props.onClick
匹配<Board onClick={...} />
它被实现为(i) => this.handleClick(i)
,其中this.handleClick(i)
指的是Game.handleClick(i)
。
你的猜测很好! 我试图在这个要点上评论代码的关键方面: https : //gist.github.com/Sangrene/d6784a855e0e3324e5b499e3a5242c45
您对onClick
函数的流程和原点的理解是正确的,它在更高级别的组件Game中定义。
Game
组件定义了onClick
方法,可以调用它来处理某些事情。
以相反的顺序,
HTML组件[ button
]给出了一个承诺,如果你给我一个与所述签名匹配的回调函数,我会在发生某些事情时调用它( 在此事件中单击 )。
现在更高的组件(按钮的父级)到按钮Square
功能,都是感兴趣的
但是因为Square函数本身没有这个事件的真实用例,所以它决定将该事件的处理委托给它的父进程与按钮一样。
但更进一步说,如果你有兴趣收到这个通知,我的合同会进一步延伸说,我只会允许通知事件当且仅当你通过我的输入对象的成员传递你的回调如onClick
。
因此,另一个更高级别的组件Board
(Square的父级)将以某种方式需要满足传递具有成员onClick
的对象的组件Square
要求。 注意一些事情, Board
的renderSquare
方法成员,
Square
的新实例时设置值和onClick
属性,然后返回该实例(因为JS支持高阶函数高阶函数 ) 它将anonymous function
定义为委托,其实现只是返回名为onClick
的道具成员( 看起来董事会还与任何潜在的父母签订了合同,必须有一个成员onClick传递给它 )...请注意,因为这句法尚未正式通过,巴别塔是用来transpile这些代码到的东西,一个典型的浏览器就明白了。
renderSquare
方法和或者本身没有对传递的onClick成员做任何事情,只是在onClick={() => this.props.onClick(i)}
中将其返回到自己的匿名函数中
我假设您知道该语句的结果将如何显示,但为了参数,它基本上成为function onClick(){return [this].props.onClick(i);}
Game
( Board
parent)是定义并提供满足onClick
( 由按钮组件定义 )方法的要求并将其作为props
传递给子组件Board
的实际实现的组件。 现在它意味着每当Board
特别从其props
遇到onClick
,它实际上将访问Game
中定义的匿名函数,该函数随后返回Game
的handleClick
函数,参见上面的3.2点。 试图回答你的问题
我的问题是我如何设定论点? 我的猜测是起点是在Board组件中调用renderSquare(i)的时候。 从那里我迷失了我如何处理clickClick(i)。 它存储在'onClick函数对象传递给SquarefromBoard`中吗?
这里要注意的最重要的事情是,所有这些代码更高的是关于代码在活动或调用时如何工作的所有蓝图或定义,将其视为一个管道。 所以定义并不意味着handleClick(i)
被立即调用,事实上直到我们的按钮组件触发事件时才会调用它,当某些事情导致/满足按钮发布事件时,当事件发生时,我刚刚尝试解释的这些步骤的反向发生,直到根游戏的handleClick
函数被调用。
我意识到我的答案可能很长,但我希望它能描绘出一条信息,并希望能帮助你形象化事物的流动。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.