我如何在 React 中更新父级的状态?
How can I update the parent's state in React?
我的结构如下:
Component 1
- |- Component 2
- - |- Component 4
- - - |- Component 5
Component 3
组件 3 应根据组件 5 的状态显示一些数据。
既然 props 是不可变的,我不能简单地将它的状态保存在组件 1 中并转发它,对吗?是的,我读过 Redux,但我不想使用它。我希望只用 React 就可以解决它。我错了吗?
对于 child-parent 通信,您应该传递一个函数,将状态从 parent 设置为 child,像这样
class Parent extends React.Component {
constructor(props) {
super(props)
this.handler = this.handler.bind(this)
}
handler() {
this.setState({
someVar: 'some value'
})
}
render() {
return <Child handler = {this.handler} />
}
}
class Child extends React.Component {
render() {
return <Button onClick = {this.props.handler}/ >
}
}
这样 child 就可以通过调用带有 props 的函数来更新 parent 的状态。
但是您将不得不重新考虑组件的结构,因为据我了解,组件 5 和组件 3 并不相关。
一种可能的解决方案是将它们包装在更高级别的组件中,该组件将包含组件 1 和组件 3 的状态。该组件将通过 props 设置较低级别的状态。
我喜欢关于传递函数的答案。这是一个非常方便的技术。
另一方面,您也可以使用 pub/sub 或使用派发器的变体来实现此目的,如 Flux 所做的那样。这个理论非常简单。让组件 5 发送组件 3 正在侦听的消息。 Component 3 然后更新它的状态,触发重新渲染。这需要有状态的组件,根据您的观点,它可能是也可能不是反模式。我个人反对他们,宁愿有其他东西自上而下地监听调度和更改状态(Redux 这样做,但它增加了额外的术语)。
import { Dispatcher } from 'flux'
import { Component } from 'React'
const dispatcher = new Dispatcher()
// Component 3
// Some methods, such as constructor, omitted for brevity
class StatefulParent extends Component {
state = {
text: 'foo'
}
componentDidMount() {
dispatcher.register( dispatch => {
if ( dispatch.type === 'change' ) {
this.setState({ text: 'bar' })
}
}
}
render() {
return <h1>{ this.state.text }</h1>
}
}
// Click handler
const onClick = event => {
dispatcher.dispatch({
type: 'change'
})
}
// Component 5 in your example
const StatelessChild = props => {
return <button onClick={ onClick }>Click me</button>
}
与 Flux 捆绑在一起的调度程序非常简单。它只是注册回调并在任何调度发生时调用它们,传递调度上的内容(在上面的简洁示例中,调度没有 payload
,只是一个消息 ID)。如果对您来说更有意义,您可以很容易地将其适应传统的 pub/sub(例如,使用事件中的 EventEmitter 或其他版本)。
每当您需要在任何级别下的子级与父级之间进行通信时,最好使用 context。在父组件中定义子组件可以调用的上下文,如:
在父组件中,在您的案例中是组件 3,
static childContextTypes = {
parentMethod: React.PropTypes.func.isRequired
};
getChildContext() {
return {
parentMethod: (parameter_from_child) => this.parentMethod(parameter_from_child)
};
}
parentMethod(parameter_from_child){
// Update the state with parameter_from_child
}
现在在子组件(在您的例子中是组件 5)中,只需告诉该组件它想要使用其父组件的上下文。
static contextTypes = {
parentMethod: React.PropTypes.func.isRequired
};
render() {
return(
<TouchableHighlight
onPress = {() => this.context.parentMethod(new_state_value)}
underlayColor='gray' >
<Text> update state in parent component </Text>
</TouchableHighlight>
)}
您可以在 this GitHub repository 中找到演示项目。
我找到了以下工作解决方案来将 onClick 函数参数从子组件传递到父组件:
带方法传递的版本()
//ChildB component
class ChildB extends React.Component {
render() {
var handleToUpdate = this.props.handleToUpdate;
return (<div><button onClick={() => handleToUpdate('someVar')}>
Push me
</button>
</div>)
}
}
//ParentA component
class ParentA extends React.Component {
constructor(props) {
super(props);
var handleToUpdate = this.handleToUpdate.bind(this);
var arg1 = '';
}
handleToUpdate(someArg){
alert('We pass argument from Child to Parent: ' + someArg);
this.setState({arg1:someArg});
}
render() {
var handleToUpdate = this.handleToUpdate;
return (<div>
<ChildB handleToUpdate = {handleToUpdate.bind(this)} /></div>)
}
}
if(document.querySelector("#demo")){
ReactDOM.render(
<ParentA />,
document.querySelector("#demo")
);
}
带箭头函数的版本
//ChildB component
class ChildB extends React.Component {
render() {
var handleToUpdate = this.props.handleToUpdate;
return (<div>
<button onClick={() => handleToUpdate('someVar')}>
Push me
</button>
</div>)
}
}
//ParentA component
class ParentA extends React.Component {
constructor(props) {
super(props);
}
handleToUpdate = (someArg) => {
alert('We pass argument from Child to Parent: ' + someArg);
}
render() {
return (<div>
<ChildB handleToUpdate = {this.handleToUpdate} /></div>)
}
}
if(document.querySelector("#demo")){
ReactDOM.render(
<ParentA />,
document.querySelector("#demo")
);
}
我找到了以下工作解决方案,将 onClick 函数参数从 child 传递到带有参数的 parent 组件:
Parent class:
class Parent extends React.Component {
constructor(props) {
super(props)
// Bind the this context to the handler function
this.handler = this.handler.bind(this);
// Set some state
this.state = {
messageShown: false
};
}
// This method will be sent to the child component
handler(param1) {
console.log(param1);
this.setState({
messageShown: true
});
}
// Render the child component and set the action property with the handler as value
render() {
return <Child action={this.handler} />
}}
Child class:
class Child extends React.Component {
render() {
return (
<div>
{/* The button will execute the handler function set by the parent component */}
<Button onClick={this.props.action.bind(this,param1)} />
</div>
)
} }
<Footer
action={()=>this.setState({showChart: true})}
/>
<footer className="row">
<button type="button" onClick={this.props.action}>Edit</button>
{console.log(this.props)}
</footer>
Try this example to write inline setState, it avoids creating another function.
我们可以创建 ParentComponent 并使用 handleInputChange 方法更新 ParentComponent 状态。导入 ChildComponent 并将两个 props 从父组件传递给子组件,即 handleInputChange 函数和 count。
import React, { Component } from 'react';
import ChildComponent from './ChildComponent';
class ParentComponent extends Component {
constructor(props) {
super(props);
this.handleInputChange = this.handleInputChange.bind(this);
this.state = {
count: '',
};
}
handleInputChange(e) {
const { value, name } = e.target;
this.setState({ [name]: value });
}
render() {
const { count } = this.state;
return (
<ChildComponent count={count} handleInputChange={this.handleInputChange} />
);
}
}
现在我们创建 ChildComponent 文件并将其保存为 ChildComponent.jsx。该组件是无状态的,因为子组件没有状态。我们使用 prop-types 库来检查 props 类型。
import React from 'react';
import { func, number } from 'prop-types';
const ChildComponent = ({ handleInputChange, count }) => (
<input onChange={handleInputChange} value={count} name="count" />
);
ChildComponent.propTypes = {
count: number,
handleInputChange: func.isRequired,
};
ChildComponent.defaultProps = {
count: 0,
};
export default ChildComponent;
我要感谢投票最多的答案让我了解我自己的问题,基本上是它与箭头函数的变体和从子组件传递参数:
class Parent extends React.Component {
constructor(props) {
super(props)
// without bind, replaced by arrow func below
}
handler = (val) => {
this.setState({
someVar: val
})
}
render() {
return <Child handler = {this.handler} />
}
}
class Child extends React.Component {
render() {
return <Button onClick = {() => this.props.handler('the passing value')}/ >
}
}
希望对大家有所帮助。
似乎我们只能将数据从父级传递给子级,因为 React 提倡单向数据流,但要让父级在其“子组件”发生某些事情时自行更新,我们通常使用所谓的“回调函数”。
We pass the function defined in the parent to the child as "props" and
call that function from the child triggering it in the parent
component.
class Parent extends React.Component {
handler = (Value_Passed_From_SubChild) => {
console.log("Parent got triggered when a grandchild button was clicked");
console.log("Parent->Child->SubChild");
console.log(Value_Passed_From_SubChild);
}
render() {
return <Child handler = {this.handler} />
}
}
class Child extends React.Component {
render() {
return <SubChild handler = {this.props.handler}/ >
}
}
class SubChild extends React.Component {
constructor(props){
super(props);
this.state = {
somethingImp : [1,2,3,4]
}
}
render() {
return <button onClick = {this.props.handler(this.state.somethingImp)}>Clickme<button/>
}
}
React.render(<Parent />,document.getElementById('app'));
HTML
----
<div id="app"></div>
在这个例子中我们可以让数据从sub child → child → parent通过将函数传递给它的直接子节点。
我多次使用此页面中评分最高的答案,但在学习 React 时,我找到了一种更好的方法,无需绑定,也无需 props 内的内联函数。
看看这里:
class Parent extends React.Component {
constructor() {
super();
this.state = {
someVar: value
}
}
handleChange = (someValue) => {
this.setState({someVar: someValue})
}
render() {
return <Child handler={this.handleChange} />
}
}
export const Child = ({handler}) => {
return <Button onClick={handler} />
}
关键在箭头函数中:
handleChange = (someValue) => {
this.setState({someVar: someValue})
}
您可以阅读更多内容here。
如果要更新父组件,
class ParentComponent extends React.Component {
constructor(props){
super(props);
this.state = {
page: 0
}
}
handler(val){
console.log(val) // 1
}
render(){
return (
<ChildComponent onChange={this.handler} />
)
}
}
class ChildComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
page: 1
};
}
someMethod = (page) => {
this.setState({ page: page });
this.props.onChange(page)
}
render() {
return (
<Button
onClick={() => this.someMethod()}
> Click
</Button>
)
}
}
这里的 onChange 是一个属性,其实例绑定了“handler”方法。我们将方法处理程序传递给 Child class 组件,通过其 props 参数中的 onChange 属性 接收。
属性 onChange 将像这样设置在 props 对象中:
props = {
onChange: this.handler
}
并传递给子组件。
因此 child 组件可以像这样访问 props 对象中 name 的值 props.onChange.
这是通过使用渲染道具完成的。
现在 child 组件有一个按钮“Click”,并设置了一个 onclick 事件,以调用通过其 props 参数对象中的 onChange 传递给它的处理程序方法。所以现在 this.props.onChange 在 child 中持有 parent class.
中的输出方法
参考文献和学分: Bits and Pieces
如果相同的场景没有到处传播,您可以使用 React 的上下文,特别是如果您不想引入状态管理库引入的所有开销。另外,它更容易学习。不过要小心;您可能会过度使用它并开始编写错误的代码。基本上你定义了一个 Container 组件(它将为你保存和保持那部分状态)让所有组件都对 writing/reading 那个数据 to/from 它的 children 感兴趣(不一定直接 children).
您也可以适当地使用普通的 React。
<Component5 onSomethingHappenedIn5={this.props.doSomethingAbout5} />
将 doSomethingAbout5 传递给组件 1:
<Component1>
<Component2 onSomethingHappenedIn5={somethingAbout5 => this.setState({somethingAbout5})}/>
<Component5 propThatDependsOn5={this.state.somethingAbout5}/>
<Component1/>
如果这是一个常见问题,您应该开始考虑将应用程序的整个状态转移到其他地方。您有几个选项,最常见的是:
基本上,不是在组件中管理应用程序状态,而是在发生某些事情时发送命令来更新状态。组件也从这个容器中提取状态,因此所有数据都是集中的。这并不意味着您不能再使用本地状态,但这是一个更高级的话题。
我是这样做的:
type ParentProps = {}
type ParentState = { someValue: number }
class Parent extends React.Component<ParentProps, ParentState> {
constructor(props: ParentProps) {
super(props)
this.state = { someValue: 0 }
this.handleChange = this.handleChange.bind(this)
}
handleChange(value: number) {
this.setState({...this.state, someValue: value})
}
render() {
return <div>
<Child changeFunction={this.handleChange} defaultValue={this.state.someValue} />
<p>Value: {this.state.someValue}</p>
</div>
}
}
type ChildProps = { defaultValue: number, changeFunction: (value: number) => void}
type ChildState = { anotherValue: number }
class Child extends React.Component<ChildProps, ChildState> {
constructor(props: ChildProps) {
super(props)
this.state = { anotherValue: this.props.defaultValue }
this.handleChange = this.handleChange.bind(this)
}
handleChange(value: number) {
this.setState({...this.state, anotherValue: value})
this.props.changeFunction(value)
}
render() {
return <div>
<input onChange={event => this.handleChange(Number(event.target.value))} type='number' value={this.state.anotherValue}/>
</div>
}
}
之前给出的大部分答案都是针对基于React.Component的设计。如果你在 React 库的最近升级中使用 useState
,那么按照 .
我们可以通过将一个函数作为 props 传递到 child 组件来从 child 组件设置 parent 状态,如下所示:
class Parent extends React.Component{
state = { term : ''}
onInputChange = (event) => {
this.setState({term: event.target.value});
}
onFormSubmit = (event) => {
event.preventDefault();
this.props.onFormSubmit(this.state.term);
}
render(){
return (
<Child onInputChange={this.onInputChange} onFormSubmit=
{this.onFormSubmit} />
)
}
}
class Child extends React.Component{
render(){
return (
<div className="search-bar ui segment">
<form className="ui form" onSubmit={this.props.onFormSubmit}>
<div class="field">
<label>Search Video</label>
<input type="text" value={this.state.term} onChange=
{this.props.onInputChange} />
</div>
</form>
</div>
)
}
}
这样,child 将更新 parent 状态 onInputChange 和 onFormSubmit 是从parent秒。这可以从 child 中的事件 listeners 调用,因此状态将在那里更新。
根据您的问题,我了解到您需要在组件 3 中显示一些基于组件 5 状态的条件数据。方法:
- 组件 3 的状态将保存一个变量来检查组件 5 的状态是否有该数据
- 一个箭头函数,它将改变组件 3 的状态变量。
- 使用 props 将箭头函数传递给组件 5。
- 组件 5 有一个箭头函数,它会改变组件 3 的状态变量
- 组件 5 的箭头函数调用加载自身
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
Class Component3 extends React.Component {
state = {
someData = true
}
checkForData = (result) => {
this.setState({someData : result})
}
render() {
if(this.state.someData) {
return(
<Component5 hasData = {this.checkForData} />
//Other Data
);
}
else {
return(
//Other Data
);
}
}
}
export default Component3;
class Component5 extends React.Component {
state = {
dataValue = "XYZ"
}
checkForData = () => {
if(this.state.dataValue === "XYZ") {
this.props.hasData(true);
}
else {
this.props.hasData(false);
}
}
render() {
return(
<div onLoad = {this.checkForData}>
//Conditional Data
</div>
);
}
}
export default Component5;
这是使用新 useState
挂钩的方法。
方法 - 将状态转换器函数作为 props 传递给子组件,并用该函数做任何您想做的事情:
import React, {useState} from 'react';
const ParentComponent = () => {
const[state, setState]=useState('');
return(
<ChildComponent stateChanger={setState} />
)
}
const ChildComponent = ({stateChanger, ...rest}) => {
return(
<button onClick={() => stateChanger('New data')}></button>
)
}
这里是获取绑定数据的两种方式的简短片段。
计数器显示父项的值并从子项更新
class Parent extends React.Component {
constructor(props) {
super(props)
this.handler = this.handler.bind(this)
this.state = {
count: 0
}
}
handler() {
this.setState({
count: this.state.count + 1
})
}
render() {
return <Child handler={this.handler} count={this.state.count} />
}
}
class Child extends React.Component {
render() {
return <button onClick={this.props.handler}>Count {this.props.count}</button>
}
}
ReactDOM.render(<Parent />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
要设置子项中父项的状态,您可以使用回调。
const Child = ({handleClick}) => (
<button on click={() => handleClick('some vale')}>change value</button>
)
const parent = () => {
const [value, setValue] = useState(null)
return <Child handleClick={setValue} />
}
在您的结构中,组件 1 和组件 3 似乎是兄弟。所以你有 3 个选择:
1-把state放到它们的parent中(不推荐4层parent-child)
2-一起使用useContext和useRducer(或useState)。
3- 使用状态管理器,如 redux、mobx ...
只需将父组件的 setState 函数通过 props 传递给子组件即可。
function ParentComp() {
const [searchValue, setSearchValue] = useState("");
return <SearchBox setSearchValue={setSearchValue} searchValue={searchValue} />;
}
然后在子组件中:
function SearchBox({ searchValue, setSearchValue }) {
return (
<input
id="search-post"
type="text"
value={searchValue}
onChange={(e) => setSearchValue(e.target.value)}
placeholder="Search Blogs ..."
/>
)
}
处理来自子组件的点击的第二个示例:
// We've below function and component in parent component
const clickHandler = (val) => {
alert(`httpRequest sent. \nValue Received: ${val}`);
};
// JSX
<HttpRequest clickHandler={clickHandler} />
这就是您从父组件获取函数然后传递一个值并触发 clickHandler
的方法。
function HttpRequest({ clickHandler }) {
const [content, setContent] = useState("initialState");
return (
<button onClick={() => clickHandler(content)}>
Send Request
</button>
);
}
export default HttpRequest;
这似乎对我有用
Parent:
...
const [open, setOpen] = React.useState(false);
const handleDrawerClose = () => {
setOpen(false);
};
...
return (
<PrimaryNavigationAccordion
handleDrawerClose={handleDrawerClose}
/>
);
Child:
...
export default function PrimaryNavigationAccordion({
props,
handleDrawerClose,
})
...
<Link
to={menuItem.url}
component={RouterLink}
color="inherit"
underline="hover"
onClick={() => handleDrawerClose()}
>
{menuItem.label}
</Link>
您可以通过将父项的引用传递给子项来实现,如:
- 在 A.js 中有一个父组件 A,方法是
updateAState
- 在 B.js
中有一个子组件 B
- 具有在 C.js
中呈现 <A><B></B></A>
的包装函数
- 在 C.js 中,您可以按如下方式使用
useRef
:
import React, { useRef } from "react";
export default function C()
{
const parentARef = useRef();
const handleChildBClick = () => parentARef.current.updateAState();
return (
<A ref={parentARef}>
<B onClick={handleChildBClick}>
</B>
</A>
);
}
指导参考:
父组件
function Parent() {
const [value, setValue] = React.useState("");
function handleChange(newValue) {
setValue(newValue);
}
// We pass a callback to Child
return <Child value={value} onChange={handleChange} />;
}
子组件
function Child(props) {
function handleChange(event) {
// Here, we invoke the callback with the new value
props.onChange(event.target.value);
}
return <input value={props.value} onChange={handleChange} />
}
我的结构如下:
Component 1
- |- Component 2
- - |- Component 4
- - - |- Component 5
Component 3
组件 3 应根据组件 5 的状态显示一些数据。
既然 props 是不可变的,我不能简单地将它的状态保存在组件 1 中并转发它,对吗?是的,我读过 Redux,但我不想使用它。我希望只用 React 就可以解决它。我错了吗?
对于 child-parent 通信,您应该传递一个函数,将状态从 parent 设置为 child,像这样
class Parent extends React.Component {
constructor(props) {
super(props)
this.handler = this.handler.bind(this)
}
handler() {
this.setState({
someVar: 'some value'
})
}
render() {
return <Child handler = {this.handler} />
}
}
class Child extends React.Component {
render() {
return <Button onClick = {this.props.handler}/ >
}
}
这样 child 就可以通过调用带有 props 的函数来更新 parent 的状态。
但是您将不得不重新考虑组件的结构,因为据我了解,组件 5 和组件 3 并不相关。
一种可能的解决方案是将它们包装在更高级别的组件中,该组件将包含组件 1 和组件 3 的状态。该组件将通过 props 设置较低级别的状态。
我喜欢关于传递函数的答案。这是一个非常方便的技术。
另一方面,您也可以使用 pub/sub 或使用派发器的变体来实现此目的,如 Flux 所做的那样。这个理论非常简单。让组件 5 发送组件 3 正在侦听的消息。 Component 3 然后更新它的状态,触发重新渲染。这需要有状态的组件,根据您的观点,它可能是也可能不是反模式。我个人反对他们,宁愿有其他东西自上而下地监听调度和更改状态(Redux 这样做,但它增加了额外的术语)。
import { Dispatcher } from 'flux'
import { Component } from 'React'
const dispatcher = new Dispatcher()
// Component 3
// Some methods, such as constructor, omitted for brevity
class StatefulParent extends Component {
state = {
text: 'foo'
}
componentDidMount() {
dispatcher.register( dispatch => {
if ( dispatch.type === 'change' ) {
this.setState({ text: 'bar' })
}
}
}
render() {
return <h1>{ this.state.text }</h1>
}
}
// Click handler
const onClick = event => {
dispatcher.dispatch({
type: 'change'
})
}
// Component 5 in your example
const StatelessChild = props => {
return <button onClick={ onClick }>Click me</button>
}
与 Flux 捆绑在一起的调度程序非常简单。它只是注册回调并在任何调度发生时调用它们,传递调度上的内容(在上面的简洁示例中,调度没有 payload
,只是一个消息 ID)。如果对您来说更有意义,您可以很容易地将其适应传统的 pub/sub(例如,使用事件中的 EventEmitter 或其他版本)。
每当您需要在任何级别下的子级与父级之间进行通信时,最好使用 context。在父组件中定义子组件可以调用的上下文,如:
在父组件中,在您的案例中是组件 3,
static childContextTypes = {
parentMethod: React.PropTypes.func.isRequired
};
getChildContext() {
return {
parentMethod: (parameter_from_child) => this.parentMethod(parameter_from_child)
};
}
parentMethod(parameter_from_child){
// Update the state with parameter_from_child
}
现在在子组件(在您的例子中是组件 5)中,只需告诉该组件它想要使用其父组件的上下文。
static contextTypes = {
parentMethod: React.PropTypes.func.isRequired
};
render() {
return(
<TouchableHighlight
onPress = {() => this.context.parentMethod(new_state_value)}
underlayColor='gray' >
<Text> update state in parent component </Text>
</TouchableHighlight>
)}
您可以在 this GitHub repository 中找到演示项目。
我找到了以下工作解决方案来将 onClick 函数参数从子组件传递到父组件:
带方法传递的版本()
//ChildB component
class ChildB extends React.Component {
render() {
var handleToUpdate = this.props.handleToUpdate;
return (<div><button onClick={() => handleToUpdate('someVar')}>
Push me
</button>
</div>)
}
}
//ParentA component
class ParentA extends React.Component {
constructor(props) {
super(props);
var handleToUpdate = this.handleToUpdate.bind(this);
var arg1 = '';
}
handleToUpdate(someArg){
alert('We pass argument from Child to Parent: ' + someArg);
this.setState({arg1:someArg});
}
render() {
var handleToUpdate = this.handleToUpdate;
return (<div>
<ChildB handleToUpdate = {handleToUpdate.bind(this)} /></div>)
}
}
if(document.querySelector("#demo")){
ReactDOM.render(
<ParentA />,
document.querySelector("#demo")
);
}
带箭头函数的版本
//ChildB component
class ChildB extends React.Component {
render() {
var handleToUpdate = this.props.handleToUpdate;
return (<div>
<button onClick={() => handleToUpdate('someVar')}>
Push me
</button>
</div>)
}
}
//ParentA component
class ParentA extends React.Component {
constructor(props) {
super(props);
}
handleToUpdate = (someArg) => {
alert('We pass argument from Child to Parent: ' + someArg);
}
render() {
return (<div>
<ChildB handleToUpdate = {this.handleToUpdate} /></div>)
}
}
if(document.querySelector("#demo")){
ReactDOM.render(
<ParentA />,
document.querySelector("#demo")
);
}
我找到了以下工作解决方案,将 onClick 函数参数从 child 传递到带有参数的 parent 组件:
Parent class:
class Parent extends React.Component {
constructor(props) {
super(props)
// Bind the this context to the handler function
this.handler = this.handler.bind(this);
// Set some state
this.state = {
messageShown: false
};
}
// This method will be sent to the child component
handler(param1) {
console.log(param1);
this.setState({
messageShown: true
});
}
// Render the child component and set the action property with the handler as value
render() {
return <Child action={this.handler} />
}}
Child class:
class Child extends React.Component {
render() {
return (
<div>
{/* The button will execute the handler function set by the parent component */}
<Button onClick={this.props.action.bind(this,param1)} />
</div>
)
} }
<Footer
action={()=>this.setState({showChart: true})}
/>
<footer className="row">
<button type="button" onClick={this.props.action}>Edit</button>
{console.log(this.props)}
</footer>
Try this example to write inline setState, it avoids creating another function.
我们可以创建 ParentComponent 并使用 handleInputChange 方法更新 ParentComponent 状态。导入 ChildComponent 并将两个 props 从父组件传递给子组件,即 handleInputChange 函数和 count。
import React, { Component } from 'react';
import ChildComponent from './ChildComponent';
class ParentComponent extends Component {
constructor(props) {
super(props);
this.handleInputChange = this.handleInputChange.bind(this);
this.state = {
count: '',
};
}
handleInputChange(e) {
const { value, name } = e.target;
this.setState({ [name]: value });
}
render() {
const { count } = this.state;
return (
<ChildComponent count={count} handleInputChange={this.handleInputChange} />
);
}
}
现在我们创建 ChildComponent 文件并将其保存为 ChildComponent.jsx。该组件是无状态的,因为子组件没有状态。我们使用 prop-types 库来检查 props 类型。
import React from 'react';
import { func, number } from 'prop-types';
const ChildComponent = ({ handleInputChange, count }) => (
<input onChange={handleInputChange} value={count} name="count" />
);
ChildComponent.propTypes = {
count: number,
handleInputChange: func.isRequired,
};
ChildComponent.defaultProps = {
count: 0,
};
export default ChildComponent;
我要感谢投票最多的答案让我了解我自己的问题,基本上是它与箭头函数的变体和从子组件传递参数:
class Parent extends React.Component {
constructor(props) {
super(props)
// without bind, replaced by arrow func below
}
handler = (val) => {
this.setState({
someVar: val
})
}
render() {
return <Child handler = {this.handler} />
}
}
class Child extends React.Component {
render() {
return <Button onClick = {() => this.props.handler('the passing value')}/ >
}
}
希望对大家有所帮助。
似乎我们只能将数据从父级传递给子级,因为 React 提倡单向数据流,但要让父级在其“子组件”发生某些事情时自行更新,我们通常使用所谓的“回调函数”。
We pass the function defined in the parent to the child as "props" and call that function from the child triggering it in the parent component.
class Parent extends React.Component {
handler = (Value_Passed_From_SubChild) => {
console.log("Parent got triggered when a grandchild button was clicked");
console.log("Parent->Child->SubChild");
console.log(Value_Passed_From_SubChild);
}
render() {
return <Child handler = {this.handler} />
}
}
class Child extends React.Component {
render() {
return <SubChild handler = {this.props.handler}/ >
}
}
class SubChild extends React.Component {
constructor(props){
super(props);
this.state = {
somethingImp : [1,2,3,4]
}
}
render() {
return <button onClick = {this.props.handler(this.state.somethingImp)}>Clickme<button/>
}
}
React.render(<Parent />,document.getElementById('app'));
HTML
----
<div id="app"></div>
在这个例子中我们可以让数据从sub child → child → parent通过将函数传递给它的直接子节点。
我多次使用此页面中评分最高的答案,但在学习 React 时,我找到了一种更好的方法,无需绑定,也无需 props 内的内联函数。
看看这里:
class Parent extends React.Component {
constructor() {
super();
this.state = {
someVar: value
}
}
handleChange = (someValue) => {
this.setState({someVar: someValue})
}
render() {
return <Child handler={this.handleChange} />
}
}
export const Child = ({handler}) => {
return <Button onClick={handler} />
}
关键在箭头函数中:
handleChange = (someValue) => {
this.setState({someVar: someValue})
}
您可以阅读更多内容here。
如果要更新父组件,
class ParentComponent extends React.Component {
constructor(props){
super(props);
this.state = {
page: 0
}
}
handler(val){
console.log(val) // 1
}
render(){
return (
<ChildComponent onChange={this.handler} />
)
}
}
class ChildComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
page: 1
};
}
someMethod = (page) => {
this.setState({ page: page });
this.props.onChange(page)
}
render() {
return (
<Button
onClick={() => this.someMethod()}
> Click
</Button>
)
}
}
这里的 onChange 是一个属性,其实例绑定了“handler”方法。我们将方法处理程序传递给 Child class 组件,通过其 props 参数中的 onChange 属性 接收。
属性 onChange 将像这样设置在 props 对象中:
props = {
onChange: this.handler
}
并传递给子组件。
因此 child 组件可以像这样访问 props 对象中 name 的值 props.onChange.
这是通过使用渲染道具完成的。
现在 child 组件有一个按钮“Click”,并设置了一个 onclick 事件,以调用通过其 props 参数对象中的 onChange 传递给它的处理程序方法。所以现在 this.props.onChange 在 child 中持有 parent class.
中的输出方法参考文献和学分: Bits and Pieces
如果相同的场景没有到处传播,您可以使用 React 的上下文,特别是如果您不想引入状态管理库引入的所有开销。另外,它更容易学习。不过要小心;您可能会过度使用它并开始编写错误的代码。基本上你定义了一个 Container 组件(它将为你保存和保持那部分状态)让所有组件都对 writing/reading 那个数据 to/from 它的 children 感兴趣(不一定直接 children).
您也可以适当地使用普通的 React。
<Component5 onSomethingHappenedIn5={this.props.doSomethingAbout5} />
将 doSomethingAbout5 传递给组件 1:
<Component1>
<Component2 onSomethingHappenedIn5={somethingAbout5 => this.setState({somethingAbout5})}/>
<Component5 propThatDependsOn5={this.state.somethingAbout5}/>
<Component1/>
如果这是一个常见问题,您应该开始考虑将应用程序的整个状态转移到其他地方。您有几个选项,最常见的是:
基本上,不是在组件中管理应用程序状态,而是在发生某些事情时发送命令来更新状态。组件也从这个容器中提取状态,因此所有数据都是集中的。这并不意味着您不能再使用本地状态,但这是一个更高级的话题。
我是这样做的:
type ParentProps = {}
type ParentState = { someValue: number }
class Parent extends React.Component<ParentProps, ParentState> {
constructor(props: ParentProps) {
super(props)
this.state = { someValue: 0 }
this.handleChange = this.handleChange.bind(this)
}
handleChange(value: number) {
this.setState({...this.state, someValue: value})
}
render() {
return <div>
<Child changeFunction={this.handleChange} defaultValue={this.state.someValue} />
<p>Value: {this.state.someValue}</p>
</div>
}
}
type ChildProps = { defaultValue: number, changeFunction: (value: number) => void}
type ChildState = { anotherValue: number }
class Child extends React.Component<ChildProps, ChildState> {
constructor(props: ChildProps) {
super(props)
this.state = { anotherValue: this.props.defaultValue }
this.handleChange = this.handleChange.bind(this)
}
handleChange(value: number) {
this.setState({...this.state, anotherValue: value})
this.props.changeFunction(value)
}
render() {
return <div>
<input onChange={event => this.handleChange(Number(event.target.value))} type='number' value={this.state.anotherValue}/>
</div>
}
}
之前给出的大部分答案都是针对基于React.Component的设计。如果你在 React 库的最近升级中使用 useState
,那么按照
我们可以通过将一个函数作为 props 传递到 child 组件来从 child 组件设置 parent 状态,如下所示:
class Parent extends React.Component{
state = { term : ''}
onInputChange = (event) => {
this.setState({term: event.target.value});
}
onFormSubmit = (event) => {
event.preventDefault();
this.props.onFormSubmit(this.state.term);
}
render(){
return (
<Child onInputChange={this.onInputChange} onFormSubmit=
{this.onFormSubmit} />
)
}
}
class Child extends React.Component{
render(){
return (
<div className="search-bar ui segment">
<form className="ui form" onSubmit={this.props.onFormSubmit}>
<div class="field">
<label>Search Video</label>
<input type="text" value={this.state.term} onChange=
{this.props.onInputChange} />
</div>
</form>
</div>
)
}
}
这样,child 将更新 parent 状态 onInputChange 和 onFormSubmit 是从parent秒。这可以从 child 中的事件 listeners 调用,因此状态将在那里更新。
根据您的问题,我了解到您需要在组件 3 中显示一些基于组件 5 状态的条件数据。方法:
- 组件 3 的状态将保存一个变量来检查组件 5 的状态是否有该数据
- 一个箭头函数,它将改变组件 3 的状态变量。
- 使用 props 将箭头函数传递给组件 5。
- 组件 5 有一个箭头函数,它会改变组件 3 的状态变量
- 组件 5 的箭头函数调用加载自身
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
Class Component3 extends React.Component {
state = {
someData = true
}
checkForData = (result) => {
this.setState({someData : result})
}
render() {
if(this.state.someData) {
return(
<Component5 hasData = {this.checkForData} />
//Other Data
);
}
else {
return(
//Other Data
);
}
}
}
export default Component3;
class Component5 extends React.Component {
state = {
dataValue = "XYZ"
}
checkForData = () => {
if(this.state.dataValue === "XYZ") {
this.props.hasData(true);
}
else {
this.props.hasData(false);
}
}
render() {
return(
<div onLoad = {this.checkForData}>
//Conditional Data
</div>
);
}
}
export default Component5;
这是使用新 useState
挂钩的方法。
方法 - 将状态转换器函数作为 props 传递给子组件,并用该函数做任何您想做的事情:
import React, {useState} from 'react';
const ParentComponent = () => {
const[state, setState]=useState('');
return(
<ChildComponent stateChanger={setState} />
)
}
const ChildComponent = ({stateChanger, ...rest}) => {
return(
<button onClick={() => stateChanger('New data')}></button>
)
}
这里是获取绑定数据的两种方式的简短片段。
计数器显示父项的值并从子项更新
class Parent extends React.Component {
constructor(props) {
super(props)
this.handler = this.handler.bind(this)
this.state = {
count: 0
}
}
handler() {
this.setState({
count: this.state.count + 1
})
}
render() {
return <Child handler={this.handler} count={this.state.count} />
}
}
class Child extends React.Component {
render() {
return <button onClick={this.props.handler}>Count {this.props.count}</button>
}
}
ReactDOM.render(<Parent />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
要设置子项中父项的状态,您可以使用回调。
const Child = ({handleClick}) => (
<button on click={() => handleClick('some vale')}>change value</button>
)
const parent = () => {
const [value, setValue] = useState(null)
return <Child handleClick={setValue} />
}
在您的结构中,组件 1 和组件 3 似乎是兄弟。所以你有 3 个选择:
1-把state放到它们的parent中(不推荐4层parent-child)
2-一起使用useContext和useRducer(或useState)。
3- 使用状态管理器,如 redux、mobx ...
只需将父组件的 setState 函数通过 props 传递给子组件即可。
function ParentComp() {
const [searchValue, setSearchValue] = useState("");
return <SearchBox setSearchValue={setSearchValue} searchValue={searchValue} />;
}
然后在子组件中:
function SearchBox({ searchValue, setSearchValue }) {
return (
<input
id="search-post"
type="text"
value={searchValue}
onChange={(e) => setSearchValue(e.target.value)}
placeholder="Search Blogs ..."
/>
)
}
处理来自子组件的点击的第二个示例:
// We've below function and component in parent component
const clickHandler = (val) => {
alert(`httpRequest sent. \nValue Received: ${val}`);
};
// JSX
<HttpRequest clickHandler={clickHandler} />
这就是您从父组件获取函数然后传递一个值并触发 clickHandler
的方法。
function HttpRequest({ clickHandler }) {
const [content, setContent] = useState("initialState");
return (
<button onClick={() => clickHandler(content)}>
Send Request
</button>
);
}
export default HttpRequest;
这似乎对我有用
Parent:
...
const [open, setOpen] = React.useState(false);
const handleDrawerClose = () => {
setOpen(false);
};
...
return (
<PrimaryNavigationAccordion
handleDrawerClose={handleDrawerClose}
/>
);
Child:
...
export default function PrimaryNavigationAccordion({
props,
handleDrawerClose,
})
...
<Link
to={menuItem.url}
component={RouterLink}
color="inherit"
underline="hover"
onClick={() => handleDrawerClose()}
>
{menuItem.label}
</Link>
您可以通过将父项的引用传递给子项来实现,如:
- 在 A.js 中有一个父组件 A,方法是
updateAState
- 在 B.js 中有一个子组件 B
- 具有在 C.js 中呈现
- 在 C.js 中,您可以按如下方式使用
useRef
:
<A><B></B></A>
的包装函数
import React, { useRef } from "react"; export default function C() { const parentARef = useRef(); const handleChildBClick = () => parentARef.current.updateAState(); return ( <A ref={parentARef}> <B onClick={handleChildBClick}> </B> </A> ); }
指导参考:
父组件
function Parent() {
const [value, setValue] = React.useState("");
function handleChange(newValue) {
setValue(newValue);
}
// We pass a callback to Child
return <Child value={value} onChange={handleChange} />;
}
子组件
function Child(props) {
function handleChange(event) {
// Here, we invoke the callback with the new value
props.onChange(event.target.value);
}
return <input value={props.value} onChange={handleChange} />
}