简体   繁体   English

React中的回调参数如何从子组件传递到父组件?

[英]How is an argument for a callback in React being passed from the child component to the parent component?

I have been working through the React tutorial at https://reactjs.org/tutorial/tutorial.html and I am getting through it well enough. 我一直在使用https://reactjs.org/tutorial/tutorial.html上的React教程,我正在通过它。 I have one thing that I haven't been able to wrap my head around though. 我有一件事我无法绕过头脑。 Here is the code in full (codepen: https://codepen.io/gaearon/pen/EmmOqJ?editors=0010 ): 这是完整的代码(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')
);

In the tutorial they pass a callback function handleClick(i) from the parent Game component to the child Board component and from there to the child Square component. 在本教程中,他们将回调函数handleClick(i)从父Game组件传递到子Board组件,并从那里传递给子Square组件。 My question is on how is the argument i set? 我的问题是如何为参数i设置? My guess is that the starting point is when renderSquare(i) is called in the Board component. 我的猜测是起点是在Board组件中调用renderSquare(i)时候。 From there I am lost as to how i it makes its way to handleClick(i) . 从那里我迷失了i如何处理handleClick(i) Is it stored in the 'onClick function object passed to Square from Board`? 它存储在'onClick function object passed to Square from Board`中吗?

My guess is that the starting point is when renderSquare(i) is called in the Board component. 我的猜测是起点是在Board组件中调用renderSquare(i)的时候。 From there I am lost as to how i it makes its way to handleClick(i) 从那里我迷失了我如何处理点击(i)

You are on the right track. 你走在正确的轨道上。

Within Board.render() , this.renderSquare(...) is called with a number 1~8 . Board.render() ,使用数字1~8调用this.renderSquare(...)

And renderSquare has an onClick handler, this.props.onClick(i) . renderSquare有一个onClick处理程序, this.props.onClick(i)

renderSquare(i) {
    return (
        <Square value={this.props.squares[i]} onClick={() => this.props.onClick(i)}/>  
    );
}

this.props is passed from the parent, Game.render() . this.props从父, Game.render()传递。
So this.props.onClick is from <Board onClick={...} /> 所以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>
        );
    }
}

So this.props.onClick matches the <Board onClick={...} /> 所以this.props.onClick匹配<Board onClick={...} />
where it's implemented as (i) => this.handleClick(i) , in which this.handleClick(i) refers to Game.handleClick(i) . 它被实现为(i) => this.handleClick(i) ,其中this.handleClick(i)指的是Game.handleClick(i)

Your guessings were good ! 你的猜测很好! I tried to comment the key aspects of the code on this gist : https://gist.github.com/Sangrene/d6784a855e0e3324e5b499e3a5242c45 我试图在这个要点上评论代码的关键方面: https//gist.github.com/Sangrene/d6784a855e0e3324e5b499e3a5242c45

You are correct in your understanding of the flow and origin of the onClick function, it is defined in the higher level component Game. 您对onClick函数的流程和原点的理解是正确的,它在更高级别的组件Game中定义。

The Game component defines the method onClick that can be invoked to handle something. Game组件定义了onClick方法,可以调用它来处理某些事情。

In reverse order, 以相反的顺序,

  1. The HTML component [ button ] gives a promise to say, if you give me a callback function that matches a said signature, I will call it whenever something happens ( clicked in this event ). HTML组件[ button ]给出了一个承诺,如果你给我一个与所述签名匹配的回调函数,我会在发生某些事情时调用它( 在此事件中单击 )。

  2. Now a higher component (parent to button) to the button Square function, is both interested in 现在更高的组件(按钮的父级)到按钮Square功能,都是感兴趣的

    • using button and 使用按钮和
    • interested in being informed when the event happens as per the promise button offered in point (1). 有兴趣根据第(1)点中提供的承诺按钮在事件发生时获得通知。

But because the Square function itself has no real use case for this event, it decided to delegate the handling of that event to its parent same way as the button did. 但是因为Square函数本身没有这个事件的真实用例,所以它决定将该事件的处理委托给它的父进程与按钮一样。

But it goes a step further to say, if you are interested in receiving this notification, my contract is further extended to say, I will only allow notification of the event if and only if you pass in your callback through a member of my input object as onClick . 但更进一步说,如果你有兴趣收到这个通知,我的合同会进一步延伸说,我只会允许通知事件当且仅当你通过我的输入对象的成员传递你的回调如onClick

  1. So another higher level component Board (parent to Square) will somehow need to satisfy component Square requirements of passing in an object with a member onClick . 因此,另一个更高级别的组件Board (Square的父级)将以某种方式需要满足传递具有成员onClick的对象的组件Square要求。 Notice some things though, the renderSquare method member of Board , 注意一些事情, BoardrenderSquare方法成员,

    • Receives as an input argument 'i' that it uses to evaluate something (...) setting the value and onClick properties when initiating a new instance of Square , and subsequently returning that instance (because JS supports Higher Order Functions Higher Order Functions ) 接收作为输入参数'i',它用于评估某些东西(...)在启动Square的新实例时设置值和onClick属性,然后返回该实例(因为JS支持高阶函数高阶函数
    • It defines an anonymous function as a delegate, of which it's implementation is just to return a member of the props called onClick ( it will appear that the Board also had a contract with any potential parent that there must be a member onClick that's passed on to it )...please note that since this syntax is not yet officially adopted, babel is used to transpile these code into something that a typical browser will understand. 它将anonymous function定义为委托,其实现只是返回名为onClick的道具成员( 看起来董事会还与任何潜在的父母签订了合同,必须有一个成员onClick传递给它 )...请注意,因为这句法尚未正式通过,巴别塔是用来transpile这些代码到的东西,一个典型的浏览器就明白了。

    • renderSquare method and or Board itself is not doing anything to the onClick member that's been passed around except just returning it in its own anonymous function on onClick={() => this.props.onClick(i)} renderSquare方法和或者本身没有对传递的onClick成员做任何事情,只是在onClick={() => this.props.onClick(i)}中将其返回到自己的匿名函数中

    I assume you know how the result of that statement will look, but for argument's sake it basically becomes function onClick(){return [this].props.onClick(i);} 我假设您知道该语句的结果将如何显示,但为了参数,它基本上成为function onClick(){return [this].props.onClick(i);}

    1. The root component Game ( Board parent), is the one that defines and provides the actual implementation that satisfies the requirements of the onClick ( as defined by button component ) method and passes it on as props to the child component Board . 根组件GameBoard parent)是定义并提供满足onClick由按钮组件定义 )方法的要求并将其作为props传递给子组件Board的实际实现的组件。 Now it means whenever Board has an encounter with the onClick specifically from its props , it will essentially be accessing the anonymous function defined in Game which subsequently returns Game 's handleClick function see point 3.2 above. 现在它意味着每当Board特别从其props遇到onClick ,它实际上将访问Game中定义的匿名函数,该函数随后返回GamehandleClick函数,参见上面的3.2点。

To attempt to answer your question 试图回答你的问题

My question is on how is the argument i set? 我的问题是我如何设定论点? My guess is that the starting point is when renderSquare(i) is called in the Board component. 我的猜测是起点是在Board组件中调用renderSquare(i)的时候。 From there I am lost as to how i it makes its way to handleClick(i). 从那里我迷失了我如何处理clickClick(i)。 Is it stored in the 'onClick function object passed toSquarefromBoard`? 它存储在'onClick函数对象传递给SquarefromBoard`中吗?

The most important thing to notice here is that, all of this code higher up is all blueprint or definitions on how the code will work when active or invoked, think of it a just a pipeline. 这里要注意的最重要的事情是,所有这些代码更高的是关于代码在活动或调用时如何工作的所有蓝图或定义,将其视为一个管道。 So the definition does not mean that the handleClick(i) is being called right away, infact it is not called up until later when our button component fires the event, when something causes / satisfied button to publish the event, of which when it happens, the reverse of these steps I've just tried to explain happens all the way down until the root Game's handleClick function gets invoked. 所以定义并不意味着handleClick(i)被立即调用,事实上直到我们的按钮组件触发事件时才会调用它,当某些事情导致/满足按钮发布事件时,当事件发生时,我刚刚尝试解释的这些步骤的反向发生,直到根游戏的handleClick函数被调用。

I realize that my answer could be very long but I hope it paints a message and hopefully helps you to sort of visualize the flow of things. 我意识到我的答案可能很长,但我希望它能描绘出一条信息,并希望能帮助你形象化事物的流动。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何测试回调单击从父组件传递的子组件? - How test callback click in child component that was passed from parent component? 如何在React Native中从子组件回调到父组件 - How to get callback from child component to parent component in React Native React中从父组件传递给子组件的“未定义”? - 'Undefined' passed from parent to child component in React? React 子组件不会更新从父组件传递的属性 - React Child Component does not update properties passed from Parent Component React JS-如何访问从父组件传递的子组件中的道具 - React JS - How to access props in a child component which is passed from a parent component 在React中没有从子组件传递给父组件的值 - Value not getting passed from child to parent component in React React,是否应该将钩子结果从父组件传递给子组件? - React, should a hook result be passed down from parent to child component? 我在 React 子组件中的 function 的参数没有传递给父组件的 function。为什么会这样? - Parameters of my function in React child component are not being passed to the parent component's function. Why is this happening? 如何从父组件中访问子组件的子进程? - How to access child component's child from parent component in react? React - Ajax 数据未传递到子组件 - React - Ajax data not being passed into Child Component
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM