【问题标题】:React passing onClick value from one class to another反应将 onClick 值从一个类传递到另一个类
【发布时间】:2018-10-09 04:43:34
【问题描述】:

在 Tournaments.js 中,我有一个锦标赛名称列表,每个名称都具有从 API 获取的唯一 ID。现在,每当我点击其中一个锦标赛名称时,我都会得到它的 ID,但我需要将此 ID 传递给 Template.js,在那里我可以根据所点击的锦标赛 ID 获取锦标赛数据。我正在尝试将道具从孩子传递给父母,但我现在完全迷失了。

Tournament.js:

import React, { Component } from "react";
import Template from './template';

const API = 'http://localhost:8080/api/tournaments';

class Tournaments extends Component {

  constructor() {
    super();
    this.state = {
      data: []
    }
  }

  componentDidMount() {
    fetch(API)
    .then((Response) => Response.json())
    .then((findresponse) => {
      console.log(findresponse)
      this.setState({
        data:findresponse,
      })
    })
  }

  reply_click(event) {
    var targetId = event.target.getAttribute('id');
    console.log(targetId);
  }

  render() {
    return(
      <div class="container">
        <div class="row">
          <div class="col-md-6 col-md-offset-3">
            <div class="jumbotron text-center">
              {
                this.state.data.map((dynamicData, key) =>
                <div>
                  <a href={"/#/template"} id={dynamicData.id} onClick={this.reply_click}>{dynamicData.name}</a>
                  <a href={"/#/addTeams"}><button type="button" class="btn-lisa">Edit</button></a>
                  <Template name={dynamicData.id}></Template>
                </div>
                )
              }
            </div>
          </div>
        </div>
      </div>
    )
  }
}

export default Tournaments;

模板.js:

import React, { Component } from "react";
import Parser from 'html-react-parser';
import Tournaments from "./Tournaments";
import './template.css';
import './index.css';

const tournyAPI = 'http://localhost:8080/api/tournaments';
const teamAPI = 'http://localhost:8080/api/teams'

class template extends Component {

  constructor() {
    super();
    this.state = {
      data: [],
    }
  }

  componentDidMount() {
    fetch(tournyAPI)
    .then((Response) => Response.json())
    .then((findresponse) => {
      this.setState({
        tournydata:findresponse.filter(res => res.id === 18),
      })
    })

所以基本上我的目标是使用 Tournament.js 中的 targetID 代替 Template.js 中 ComponentDidMount 中的“18”

【问题讨论】:

    标签: reactjs api react-router react-props


    【解决方案1】:

    targetID 添加到您的父状态并作为道具传递给孩子:

    reply_click(event) {
      var targetId = event.target.getAttribute('id');
      this.setState({ targetID });
    }
    <Template targetID={this.state.targetID}
    

    Template 中,您可以使用this.props.targetID 访问它。

    您需要使用componentDidUpdate,请参阅React Child component don't update when parent component's state update

    【讨论】:

    • 这个方法也给了我未定义的无法读取属性'setState'。
    • 你需要在你的构造函数中绑定方法:this.reply_click = this.reply_click.bind(this),或者声明为reply_click = event =&gt; {
    • 谢谢,消除了错误,但在 Template.js {this.props.targetID} 内仍然返回 undefined
    • 你用this.state = { targetID: null }初始化状态了吗?您还需要将您的componentDidMount 更改为componentDidUpdate;请参阅我上面提供的链接。
    【解决方案2】:

    在您的示例中,这非常简单,因为您在循环中渲染&lt;Template&gt;,您可以将其作为参数传递

    问题 1

    React 的目的不是像这样操作 dom var targetId = event.target.getAttribute('id') 你有这个 id,为什么要从 DOM 中获取它?而不是接受它作为参数

     <a href={"/#/template"} id={dynamicData.id} onClick={(e) => this.reply_click(e, dynamicData.id)}>{dynamicData.name}</a>
    

    reply_click(event, targetId) {
    
        console.log(targetId);
      }
    

    永远不要在 React 中查询 DOM。由于未安装的元素等,您会遇到混乱和错误。React 使用 JSDom(在内存中)而不是 Real DOM

    问题 2

    只需将其作为参数传递

    并在reply_click 中调用 setState

    reply_click(event, targetId) {
    
        console.log(targetId);
        this.setState({targetID: targetId})
      }
    

    【讨论】:

    • 尝试使用此方法,现在我收到 TypeError: Cannot read property 'setState' of undefined。我还将 targetID 添加到构造函数的 this.state 部分
    • 你没有改变我发送的链接......它有 onClick={() => this.reply_click} 它将用这个上下文包装回调
    【解决方案3】:

    您应该将此值保留在父组件state 中,并将其作为道具传递给子组件。

    当您的onClick 被解雇时,您应该更新父母state,以便更新的props 将传递给孩子。

    代码如下:

    Tournament.js

    import React, { Component } from "react";
    import Template from './template';
    
    const API = 'http://localhost:8080/api/tournaments';
    
    class Tournaments extends Component {
    
      constructor() {
        super();
        this.state = {
          data: [],
          targetId: null,
        }
      }
    
      componentDidMount() {
        fetch(API)
        .then((Response) => Response.json())
        .then((findresponse) => {
          console.log(findresponse)
          this.setState({
            data:findresponse,
          })
        })
      }
    
      reply_click = id => {
        return () => {
            this.setState({ targetId: id })
        }
      }
    
      render() {
        return(
          <div class="container">
            <div class="row">
              <div class="col-md-6 col-md-offset-3">
                <div class="jumbotron text-center">
                  {
                    this.state.data.map((dynamicData, key) =>
                    <div>
                      <a href={"/#/template"} onClick={this.reply_click(dynamicData.id)}>{dynamicData.name}</a>
                      <a href={"/#/addTeams"}><button type="button" class="btn-lisa">Edit</button></a>
                      <Template name={dynamicData.id} targetId={this.state.targetId}></Template>
                    </div>
                    )
                  }
                </div>
              </div>
            </div>
          </div>
        )
      }
    }
    
    export default Tournaments;
    

    Template.js

    import React, { Component } from "react";
    import Parser from 'html-react-parser';
    import Tournaments from "./Tournaments";
    import './template.css';
    import './index.css';
    
    const tournyAPI = 'http://localhost:8080/api/tournaments';
    const teamAPI = 'http://localhost:8080/api/teams'
    
    class template extends Component {
    
      constructor() {
        super();
        this.state = {
          data: [],
        }
      }
    
      componentDidMount() {
        fetch(tournyAPI)
        .then((Response) => Response.json())
        .then((findresponse) => {
          this.setState({
            tournydata: findresponse.filter(res => res.id === this.props.targetId),
          })
        })
    

    但是,如果您想在每次更改 targetId 后保持更新您的 模板 组件,请使用 componentDidUpdate 而不是 componentDidMount

    像这样:

    Template.js

    componentDidUpdate(prevProps) {
        if (prevProps.targetId !== this.props.targetId) {
           fetch(tournyAPI)
           .then((Response) => Response.json())
           .then((findresponse) => {
           this.setState({
              tournydata:findresponse.filter(res => res.id === this.props.targetId),
           })
          })
        }
    }
    

    如果您需要在第一次渲染期间立即执行此操作,只需在您的 Tournament 组件中添加检查 targetId 是否不是 null

    类似这样的:

    Tournament.js

    render() {
        ...
        {this.state.targetId ? <Template name={dynamicData.id} targetId={this.state.targetId}></Template> : null }
        ...
    }
    

    【讨论】:

    • 试过了,但是 {this.props.targetId} 在 Template.js 中返回 undefined 另外, 是否需要在渲染内部或确实它也可以在渲染之外工作?
    • @Ferder 我已经在我的回答中更新了你的 reply_click 函数。像这样使用它。
    • @Ferder 你是怎么试过的,用哪一个? componentDidMountcomponentDidUpdate?
    • componentDidUpdate
    • @Ferder 尝试将它与更新的reply_click 函数一起使用并像我一样更改onClick
    猜你喜欢
    • 2011-08-26
    • 1970-01-01
    • 1970-01-01
    • 2013-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多