ตอบสนอง js เปลี่ยนสถานะขององค์ประกอบลูกจากองค์ประกอบหลัก


100

ฉันมีองค์ประกอบสองส่วน: องค์ประกอบหลักที่ฉันต้องการเปลี่ยนสถานะขององค์ประกอบลูก:

class ParentComponent extends Component {
  toggleChildMenu() {
    ?????????
  }
  render() {
    return (
      <div>
        <button onClick={toggleChildMenu.bind(this)}>
          Toggle Menu from Parent
        </button>
        <ChildComponent />
      </div>
    );
  }
}

และส่วนประกอบของเด็ก :

class ChildComponent extends Component {
  constructor(props) {
    super(props);
    this.state = {
      open: false;
    }
  }

  toggleMenu() {
    this.setState({
      open: !this.state.open
    });
  }

  render() {
    return (
      <Drawer open={this.state.open}/>
    );
  }
}

ฉันจำเป็นต้องเปลี่ยนสถานะเปิดของคอมโพเนนต์ลูกจากคอมโพเนนต์หลักหรือเรียกใช้toggleMenu ()ของคอมโพเนนต์ลูกจากคอมโพเนนต์หลักเมื่อคลิกปุ่มในคอมโพเนนต์หลัก


บางทีคุณอาจถือข้อมูลอ้างอิงของเด็กในผู้ปกครองและเปลี่ยนสถานะของเด็กอย่างชัดเจนดูเอกสาร
Chaojun Zhong

คำตอบ:


125

รัฐควรได้รับการจัดการในองค์ประกอบหลัก คุณสามารถโอนopenค่าไปยังคอมโพเนนต์ลูกโดยการเพิ่มคุณสมบัติ

class ParentComponent extends Component {
   constructor(props) {
      super(props);
      this.state = {
        open: false
      };

      this.toggleChildMenu = this.toggleChildMenu.bind(this);
   }

   toggleChildMenu() {
      this.setState(state => ({
        open: !state.open
      }));
   }

   render() {
      return (
         <div>
           <button onClick={this.toggleChildMenu}>
              Toggle Menu from Parent
           </button>
           <ChildComponent open={this.state.open} />
         </div>
       );
    }
}

class ChildComponent extends Component {
    render() {
      return (
         <Drawer open={this.props.open}/>
      );
    }
}

สามารถใช้เพื่อควบคุมคุณสมบัติ css เช่น 'display' ได้หรือไม่? เช่นเดียวกับในกรณีที่ prop ของฉัน 'open' มี 'none' หรือ 'inline-block' การแสดงผล css prop จะได้รับการอัพเดตหรือไม่?
deusofnull

3
ใช่นั่นคือสิ่งที่แพคเกจ react-classnames ทำ แต่ยังช่วยให้คุณสามารถใช้ชุดชื่อชั้นเรียนและใช้ชื่ออื่นตามเงื่อนไขได้ เช่นนี้: classNames({ foo: true, bar: this.props.open });// => 'foo' เมื่อ this.props.open = false และ 'foo bar' เมื่อ this.props.open = true
deusofnull

1
เราจะเปลี่ยนสถานะเปิดในองค์ประกอบลูกได้อย่างไร
Priyabrata Atha

1
คุณสามารถเพิ่มคุณสมบัติtoggleให้กับ ChildComponent <ChildComponent open={this.state.open} toggle={this.toggleChildMenu.bind(this)} />และเรียกthis.props.toggle()ในองค์ประกอบลูก
Olivier Boissé

1
ฉันไม่เข้าใจคุณสามารถเรียกมันได้ทุกที่ที่คุณต้องการในองค์ประกอบลูกทันทีที่คุณระบุคุณสมบัตินี้เมื่อประกาศChildComponent-><ChildComponent toggle={this.toggleChildMenu.bind(this)} />
Olivier Boissé

25

องค์ประกอบหลักสามารถจัดการสถานะลูกที่ส่งผ่านเสาไปยังลูกและลูกจะแปลงเสานี้ในสถานะโดยใช้ componentWillReceiveProps

class ParentComponent extends Component {
  state = { drawerOpen: false }
  toggleChildMenu = () => {
    this.setState({ drawerOpen: !this.state.drawerOpen })
  }
  render() {
    return (
      <div>
        <button onClick={this.toggleChildMenu}>Toggle Menu from Parent</button>
        <ChildComponent drawerOpen={this.state.drawerOpen} />
      </div>
    )
  }
}

class ChildComponent extends Component {
  constructor(props) {
    super(props)
    this.state = {
      open: false
    }
  }

  componentWillReceiveProps(props) {
    this.setState({ open: props.drawerOpen })
  }

  toggleMenu() {
    this.setState({
      open: !this.state.open
    })
  }

  render() {
    return <Drawer open={this.state.open} />
  }
}

1
ในการตอบสนอง 16 ใช้ getDerivedStateFromProps
Fadi Abo Msalam

1
@FadiAboMsalam ฉันใช้ react เวอร์ชัน 16.7.0 กับ @ types / react เวอร์ชัน 16.7.18 อย่างน้อยในฝั่ง TypeScript ดูเหมือนจะgetDerivedStateFromProps()ไม่มี อย่างไรก็ตามคำตอบของ Miguel ที่แนะนำให้ใช้componentWillReceiveProps(props)นั้นมีอยู่และใช้งานได้ดีในสภาพแวดล้อมของฉัน
Manfred

ในกรณีนี้สถานะ toggleMenu () จะเปลี่ยนไปอย่างไรภายในองค์ประกอบลูกจะไปถึงพาเรนต์ ลองนึกภาพว่าฉันปิดลิ้นชักส่วนประกอบหลักจะรู้ได้อย่างไรว่าปิดแล้ว
norman123123

20

คำตอบข้างต้นถูกต้องสำหรับฉันบางส่วน แต่ในสถานการณ์ของฉันฉันต้องการตั้งค่าเป็นสถานะเนื่องจากฉันใช้ค่านี้เพื่อแสดง / สลับโมดอล ดังนั้นฉันได้ใช้เช่นด้านล่าง หวังว่ามันจะช่วยใครสักคน

class Child extends React.Component {
  state = {
    visible:false
  };

  handleCancel = (e) => {
      e.preventDefault();
      this.setState({ visible: false });
  };

  componentDidMount() {
    this.props.onRef(this)
  }

  componentWillUnmount() {
    this.props.onRef(undefined)
  }

  method() {
    this.setState({ visible: true });
  }

  render() {
    return (<Modal title="My title?" visible={this.state.visible} onCancel={this.handleCancel}>
      {"Content"}
    </Modal>)
  }
}

class Parent extends React.Component {
  onClick = () => {
    this.child.method() // do stuff
  }
  render() {
    return (
      <div>
        <Child onRef={ref => (this.child = ref)} />
        <button onClick={this.onClick}>Child.method()</button>
      </div>
    );
  }
}

อ้างอิง - https://github.com/kriasoft/react-starter-kit/issues/909#issuecomment-252969542


2
นี่คือสิ่งที่ฉันต้องการ แต่ฉันสงสัยว่าทำไมไม่ใช้ react refs? ดูdoc
Chaojun Zhong

onRef prop ทำอะไร?
norman123123

2

คุณสามารถใช้ createRef เพื่อเปลี่ยนสถานะขององค์ประกอบลูกจากคอมโพเนนต์หลัก นี่คือขั้นตอนทั้งหมด

  1. สร้างวิธีการเพื่อเปลี่ยนสถานะในองค์ประกอบลูก

    2 - สร้างการอ้างอิงสำหรับองค์ประกอบลูกในองค์ประกอบหลักโดยใช้ React.createRef ()

    3 - แนบการอ้างอิงกับองค์ประกอบลูกโดยใช้ ref = {}

    4 - เรียกเมธอดองค์ประกอบลูกโดยใช้ this.yor-reference.current.method

องค์ประกอบหลัก


class ParentComponent extends Component {
constructor()
{
this.changeChild=React.createRef()
}
  render() {
    return (
      <div>
        <button onClick={this.changeChild.current.toggleMenu()}>
          Toggle Menu from Parent
        </button>
        <ChildComponent ref={this.changeChild} />
      </div>
    );
  }
}

ส่วนประกอบย่อย


class ChildComponent extends Component {
  constructor(props) {
    super(props);
    this.state = {
      open: false;
    }
  }

  toggleMenu=() => {
    this.setState({
      open: !this.state.open
    });
  }

  render() {
    return (
      <Drawer open={this.state.open}/>
    );
  }
}




1

คุณสามารถส่ง prop จากพาเรนต์และใช้ในคอมโพเนนต์ลูกได้ดังนั้นคุณจะกำหนดพื้นฐานการเปลี่ยนแปลงสถานะของเด็กบนการเปลี่ยนแปลง prop ที่ส่งและคุณสามารถจัดการสิ่งนี้ได้โดยใช้getDerivedStateFromPropsในองค์ประกอบลูก

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.