簡體   English   中英

在反應中從父組件訪問子組件的子狀態

[英]Access child state of child from parent component in react

我想從父組件訪問<Child2>狀態。

<Parent>
   <Child1>
      <Child2>
   </Child1>
</Parent>

如何實現?

你根本不應該這樣做。 在反應中,信息應該總是從上到下流動。 執行此操作的反應方式是將狀態提升到父級並將值作為道具向下傳遞。 在您的孩子中,您的回調也作為孩子調用的道具傳遞,當值發生變化時(例如通過用戶交互),以便父母可以更新其狀態:

const Child = ({ value, onChange }) => (
  <Fragment>
    <p>{value || "no value"}</p>
    <button onClick={() => onChange('changed')} >Set value</button>
  </Fragment>
);

class Parent extends Component {
  state = {
    value: null
  };

  handleChange = value => this.setState({value})

  render() {
    return <Child value={this.state.value} onChange={this.handleChange} />;
  }
}

代碼沙盒上的工作示例

這可以無限深嵌套完成。 在一個更大的應用程序中,您的狀態需要在遍布組件樹的多個組件中使用,您可能會達到一個點,即獲得 PITA。 克服這個問題的常用方法是使用像redux提供的全局存儲。

避免將 props 傳遞給多個組件的一種方法是使用 reacts context api。

這允許我們從MyProvider組件向下訪問 100 個子組件的狀態,而無需手動將 props 向下傳遞到 100 個子組件。

import React, { Component } from "react";
import { render } from "react-dom";

// first make a new context
const MyContext = React.createContext();

// Then Create a provider Component
class MyProvider extends Component {
  state = {
    name: "Junie",
    age: 21
  };
  render() {
    return (
      <MyContext.Provider
        value={{
          state: this.state,
          increment: () => this.setState({ age: this.state.age + 1 })
        }}
      >
        {this.props.children}
      </MyContext.Provider>
    );
  }
}

const App = () => {
  return (
    <MyProvider>
      <div>
        <p>Hello I'm the App </p>
        <Child />
      </div>
    </MyProvider>
  );
};

const Child = props => {
  return (
    <div>
      <Child2 />
    </div>
  );
};

class Child2 extends Component {
  render() {
    return (
      <div>
        <p> Im Child 2 </p>
        <MyContext.Consumer>
          {context => (
            <div>
              {" "}
              <p>
                {" "}
                Inside the context consumer: {context.state.name}{" "}
                {context.state.age}
              </p>{" "}
              <button onClick={context.increment}>Update Age </button>
            </div>
          )}
        </MyContext.Consumer>
      </div>
    );
  }
}

render(<App />, document.getElementById("root"));

編輯堆棧溢出上下文示例傳遞給第二個孩子

使用context可能是您正在尋找的。

還有另一種實現。

class Parent extends React.Component {

state={childstate:''}

getFromChild = (value) => {
 this.setState({childstate:value})
}

 render() {
  return (
   <div> 
    <Child1 getFromChild={this.getFromChild/> 
    {this.state.childstate && <div> {this.state.childstate} </div>} 
   </div>
  )
 }
}

const Child1 = (props) => <Child2 getFromChild={props.getFromChild}/>

class Child2 extends React.Component {
state={somevalue:10}

sendValue = (value) => this.props.getFromChild(value)

render() {
 return (
   <div>
    <button onClick={() => this.sendValue(this.state.somevalue)} /> 
   </div>
  )
 }
}

很簡單,我們在父級中使用 setter 來獲取相應子級的狀態。

我們將一個值作為參數並將父狀態的狀態設置為該值。 我將其命名為 childstate,因此很清楚我們發送給父級的任何值都來自子級。

getFromChild = (value) => this.setState({childstate:value})

將函數作為道具從Child1傳遞給Child2

<Child2 getFromChild={props.getFromChild}/>

Child2添加 onClick 處理程序以將值從子級發送到Parent

<button onClick={() => this.sendValue(this.state.somevalue)} />

可以通過將 ref 從父組件傳遞給子組件來解決問題。 子組件應該被包裹在 forwardRef 中。 現在破解是每當您更新子狀態時,也要同時更新該引用。

完成此操作。 您可以訪問所有子狀態,因為它也保存在 ref 中。

const QEditor = (props, ref) => {
  const [content, setContent] = useState(initialContent);

  const handleChange = useCallback(
    value => {
        /* not all components passes ref */
      if (ref?.current) {
        /* setting the value on ref also */
        ref.current.content = value;
      }
      setContent(value);
    },
    [ref]
  );
... trim...


export default forwardRef(QEditor);
... 
// in parent
const Parent = () => {
  const newRef = useRef({});
  cosole.log(newRef) // this will contain child's state.
  return <QEditor ref={newRef} />
} 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM