如何在单击时从另一个兄弟组件中增加一个值?

Posted

技术标签:

【中文标题】如何在单击时从另一个兄弟组件中增加一个值?【英文标题】:How to increment a value in one sibling component from another on click? 【发布时间】:2019-02-13 11:07:03 【问题描述】:
function LeagueBadge(props) 
    return (
        <img src=props.badgeUrl  />
    );


class LeagueInfo extends Component 
    constructor(props) 
        super(props);
        this.state = 
            amountOfPlayers: null,
            rpPerSecond: null,
            rpCost: null,
        ;
    
    render() 
        return (
            <div>
                <h4>this.props.name players: this.props.amountOfPlayers</h4>
                <h4>RP per second: this.props.rpPerSecond</h4>
                <h4>RP cost: this.props.rpCost</h4>
            </div>
        );
    


class League extends Component 
    render() 
        return (
            <div>
                <LeagueBadge badgeUrl=this.props.badge />
                <LeagueInfo name=this.props.name />
            </div>
        );
    


class App extends Component 
    render() 
        return (
            <div className="App">
                <h1>Players</h1>
                <League name="Bronze" badge= require('./bronze.png') ></League>
                <League name="Silver" badge= require('./silver.png') ></League>
                <League name="Gold" badge= require('./gold.png') ></League>
                <League name="Platinum" badge= require('./platinum.png') ></League>
                <League name="Diamond" badge= require('./diamond.png') ></League>
                <League name="Master" badge= require('./master.png') ></League>
                <League name="Challenger" badge= require('./challenger.png') ></League>
            </div>
        );
    

我希望能够单击作为 LeagueBadge 组件的图像,并在其兄弟 LeagueInfo 中增加 amountOfPlayers 的值。我已经用谷歌搜索了反应兄弟姐妹的交流,只找到了带有输入标签和 onChange 的示例,但在这里我想要 img 标签或按钮和 onClick。

【问题讨论】:

【参考方案1】:

您可以将amountOfPlayers 的状态提升到您的&lt;Leauge /&gt; 组件中,这样: - 可以从&lt;LeagueBadge /&gt; 触发更新 - 而且,该状态可以传递给您的 &lt;LeagueInfo /&gt; 组件

这将允许您根据需要在 &lt;LeagueInfo /&gt;&lt;LeagueBadge /&gt; 兄弟姐妹之间共享和同步状态。

为此,您需要向&lt;LeagueBadge /&gt; 添加一个onClick 回调,当点击img 元素时会触发该回调。在&lt;Leauge /&gt; 渲染方法中,您可以提供在&lt;Leauge /&gt; 中增加amountOfPlayers 状态的逻辑。当amountOfPlayers 增加并调用setState 时(在&lt;Leauge /&gt; 中),这反过来会导致您的&lt;Leauge /&gt; 组件重新渲染自己(和孩子/兄弟姐妹)。因为amountOfPlayers 的更新值作为prop 传递给&lt;LeagueInfo /&gt; 组件,所以这个更新值将在&lt;LeagueInfo /&gt; 中呈现——有效地实现您所追求的。

这样的事情可能对你有用:

class LeagueBadge extends Component 
    render() 

    // Add props.onClick callback to trigger click event in <League /> 
    // component
    return (
        <img src=this.props.badgeUrl  
             onClick=() => this.props.onClick() />
    );
    


class LeagueInfo extends Component 
    constructor(props) 
        super(props);
        this.state = 
            // amountOfPlayers: null, // This is not needed, as it's supplied by props
            rpPerSecond: null,
            rpCost: null,
        ;
    
    render() 
        return (
            <div>
                <h4>this.props.name players: this.props.amountOfPlayers</h4>
                <h4>RP per second: this.props.rpPerSecond</h4>
                <h4>RP cost: this.props.rpCost</h4>
            </div>
        );
    


class League extends Component 

    componentWillMount() 

        this.setState(
            amountOfPlayers : 0
        )
    

    render() 

        // Locally defined function that increments amountOfPlayers and
        // updates state
        const incrementAmountOfPlayers  = () => 
            this.setState( amountOfPlayers : 
            this.state.amountOfPlayers + 1 )
        

        return (
            <div>
                <LeagueBadge badgeUrl=this.props.badge 
                             onClick= () => incrementAmountOfPlayers()  />
                <LeagueInfo name=this.props.name amountOfPlayers= this.state.amountOfPlayers  />
            </div>
        );
    

【讨论】:

目前我只复制粘贴了您的解决方案,但它在&lt;img src=props.badgeUrl alt="missing alt text" onClick=() =&gt; this.props.onClick() /&gt; PS 中显示错误“TypeError:无法读取未定义的属性'props'”。我通过从第二个道具中删除 this. 来修复它 @Megoh 刚刚更新 - 你现在应该可以复制了 不确定我是否需要在那里上课。也许未来只是功能就足够了 @Megoh 你的意思是&lt;LeagueBadge /&gt; 组件?如果您希望我更新该答案以使其成为功能组件,请告诉我 我已经让 LeagueBadge 成为一个功能组件,并从第二个道具中删除了 this. 以使其工作。非常感谢,我很高兴在这么多天后解决了这个问题。【参考方案2】:

将您的状态保存在联赛组件中,并将负责更改它的函数传递给 LeagueBadge,例如:

class League extends Component 
    constructor(props) 
        super(props);
        this.state = 
            amountOfPlayers: null,
        ;
    
    handleClick = () => 
    this.setState(prevState => 
       return amountOfPlayers: prevState.amountOfPlayers + 1
    )
  
    render() 
        return (
            <div>
                <LeagueBadge badgeUrl=this.props.badge incrementPlayers=this.handleClick/>
                <LeagueInfo name=this.props.name amountOfPlayers=this.state.amountOfPlayers/>
            </div>
        );
    



function LeagueBadge(props) 
    return (
        <img src=props.badgeUrl  onClick=this.props.incrementPlayers/>
    );

在您的信息组件中使用this.props.amountOfPlayers

【讨论】:

我也会检查您的解决方案,如果可行,请点赞。它可以工作,但是它在开头显示 null 而不是 0,但这没什么大不了的。

以上是关于如何在单击时从另一个兄弟组件中增加一个值?的主要内容,如果未能解决你的问题,请参考以下文章

单击按钮时从同一组件中清除数据

如何在单击时从 Column(0) 中的列表框中引用值?

如何在将 Tablayout 与 viewpager 一起使用时从另一个片段调用 AsyncTask?

从另一个组件更新组件状态的最简单方法是啥?可以说组件是兄弟姐妹吗?

从另一个组件调用一个组件中的函数

如何在使用 UIpageviewcontroller 导航页面时从另一个视图控制器自动更新视图控制器上的标签