在 ReactJS 中通过父状态的 props 传递函数
这可能有点令人困惑,所以我会尽量简化它。
我的状态包含父组件
App.js
中的对象数组。这是一个对象的示例。
{
category: "sample category",
API: "API URL",
active: function()
}
在我的子组件
Category.js
中,我通过 prop 传递了该数组。子组件渲染
ul
,然后映射到数组上以为每个类别创建一个
li
。每个列表项都应该有一个 onClick 事件,该事件触发对象中关联的
active: function()
。
由于某种原因,这不起作用。如果我运行测试,其中函数是一个简单的
console.log("success")
,那就没问题了。因此,列表项正在选择该函数并通过我的 props 正常运行它。
这让我相信问题出在我正在运行的实际函数上。我尝试运行的函数是这个(位于
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
的状态吗?
编辑:这里有更多代码可帮助您找出解决方案。
实际错误:Uncaught TypeError:无法读取 catMovies (App.js:71) 中未定义的属性“setState”
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>
);
您的问题在于处理程序的绑定。
您不应该像在构造函数中那样覆盖处理程序,而应该直接在状态初始化中执行此操作:
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>
该问题可能是由于此函数中的
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