首页 文章

在ReactJS中通过来自父状态的道具传递函数

提问于
浏览
1

所以这可能有点令人困惑所以我会尽力简化它 .

我的状态包含父组件 App.js 中的对象数组 . 这是一个对象的例子 .

{
category: "sample category",
API: "API URL",
active: function()
}

在我的子组件 Category.js 中,我将该数组传递给了一个道具 . 子渲染 ul 然后映射数组以为每个类别创建 li . 每个列表项都应该有一个onClick事件,该事件触发对象中的关联 active: function() .

由于某种原因,这是行不通的 . 如果我运行一个测试,其中函数是一个简单的 console.log("success") ,这没问题 . 所以列表项是通过我的道具获取功能并运行它 .

这让我相信's the actual function which I'运行's the issue. The function I' m试图运行是这个(位于 App.js

function() {
  this.setState({categoryActive: "https://opentdb.com/api.php?amount=20&category=11"});
  this.setState({showQuestions: true});
}

设置的那些状态在 App.js 中,并且该函数也位于 App.js 中,但是正在 Category.js 中的列表项目中通过prop运行 . 这是我的问题吗?我是否可以通过子组件中的函数运行来调整 App.js 的状态?


编辑:这里有更多的代码来帮助找出解决方案 .

实际错误:未捕获的TypeError:无法在catMovies中读取未定义的属性'setState'(App.js:71)

App.js:71是我的 catMovies() 函数的 this.setState({categoryActive: "https://opentdb.com/api.php?amount=20&category=11"}); .

我的 App.js 构造函数

constructor(props) {
super(props);
this.state = {
  showCategories: false,
  showQuestions: false,
  isQuestionLoaded: false,
  categories: [{
    category: "movies",
    API: "https://opentdb.com/api.php?amount=10&category=11",
    active: this.catMovies
  }, {
    category: "sports",
    API: "https://opentdb.com/api.php?amount=10&category=21",
    active: this.catSports
  }, {
    category: "books",
    API: "https://opentdb.com/api.php?amount=10&category=10",
    active: this.catBooks
  }, {
    category: "videogames",
    API: "https://opentdb.com/api.php?amount=10&category=15",
    active: this.catVideogames
  }, {
    category: "general",
    API: "https://opentdb.com/api.php?amount=10&category=9",
    active: this.catGeneral
  }, {
    category: "everything",
    API: "https://opentdb.com/api.php?amount=10",
    active: this.catEverything
  }],
  categoryActive: "",
  questionNumber: 0,
  questionTotal: null,
  correct: [],
  score: 0,
  showFinal: false,
  testState: "test"
};
this.showCategories = this.showCategories.bind(this);
this.showQuestions = this.showQuestions.bind(this);
this.catMovies = this.catMovies.bind(this);
}

这是 App.js 中的实际功能:

catMovies() {
  this.setState({categoryActive: "https://opentdb.com/api.php?amount=20&category=11"});
  this.setState({showQuestions: true});
}

以下是 App.js 的回复,称为儿童权益:

<Categories categoryList={ this.state.categories } onClick={ this.catMovies } />

最后,这里是子组件中使用所有这些的映射:

const categoryListItems = this.props.categoryList.map(cat =>
  <a href="#questionsContainer" key={cat.category + "link"}>
    <li onClick={cat.active} key={cat.category}>
      {cat.category}
    </li>
  </a>
);

2 回答

  • 3

    你的问题在于处理程序的绑定 .
    而不是像在构造函数中那样覆盖处理程序,而应该直接在状态初始化中执行:

    this.state = {
      showCategories: false,
      showQuestions: false,
      isQuestionLoaded: false,
      categories: [{
        category: "movies",
        API: "https://opentdb.com/api.php?amount=10&category=11",
        active: this.catMovies.bind(this) // <-- you need to bind here
      },
     //...
    

    下面是两个模式的运行示例,请注意 turnOff 处理程序将如何抛出相同的错误:

    const LightBall = ({ on }) => {
      return (
        <div>{`The light is ${on ? 'On' : 'Off'}`}</div>
      );
    }
    
    class App extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          lightOn: false,
          toggle: this.toggleLight.bind(this), // this will work
          turnOff: this.turnOff // this will not work
        };
        this.turnOff = this.turnOff.bind(this);
      }
    
      toggleLight(){this.setState({ lightOn: !this.state.lightOn })};
    
      turnOff() { this.setState({ lightOn: false }) };
    
      render() {
        const { lightOn, toggle, turnOff } = this.state;
        return (
          <div>
            <button onClick={toggle}>Toggle Light</button>
            <button onClick={turnOff}>Turn Off</button>
            <LightBall on={lightOn} />
          </div>
        );
      }
    }
    
    ReactDOM.render(<App />, document.getElementById("root"));
    
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
    <div id="root"></div>
    
  • 0

    这个问题可能是由于这个功能导致的

    function() {
      this.setState({categoryActive: "https://opentdb.com/api.php?amount=20&category=11"});
      this.setState({showQuestions: true});
    }
    

    this 是指调用该函数的类 .

    您可以通过使用 bind() 将数组传递给子节点之前将函数绑定到 App 组件来解决此问题(请参阅此处https://developer.mozilla.org/it/docs/Web/JavaScript/Reference/Global_Objects/Function/bind

    或者您可以使用箭头函数,如果您在 App 组件中定义它以自动将其范围绑定到该组件,所以

    {
    category: "sample category",
    API: "API URL",
    active: () => {
        this.setState({categoryActive: "https://opentdb.com/api.php?amount=20&category=11"});
        this.setState({showQuestions: true});
      }
    }
    

    在这里查看有关箭头功能的更多信息https://babeljs.io/learn-es2015/#arrows-and-lexical-this

相关问题