如何从父组件访问嵌套组件?

How can I accessing nested component in react from parent component?

我想从父组件访问嵌套组件。

我是比尔Form.jsx

      import BillDetailForm from './BillDetailForm';


         render(){

          return (
            <form onSubmit={handleSubmit}>

             <FieldArray

               name= 'detail'
               component={BillDetailForm}
               placeholder= '...detail'
               label='Detail'

                 />
               </form>
                  );
                   }
               }

BillForm 是父组件。

这是 BillForm 的嵌套组件或子组件:BillDetailForm.jsx

     render(){


    return(
         <form onSubmit={ handleSubmit }>


       <div>Detail:</div>
      <FieldArray
        name= 'detail'
        component={RenderDetail}
        label='Detail'
      />

      </form>

    )

} 

BillDetailForm 内部是 RenderDetail:

        const RenderDetail = ({fields, meta: { error,submitFailed}},props) => (
          <dl>
         <dt>
            <button type="button" className= 'btn btn-primary' onClick={() => fields.push()}>Add 
        Detail</button>
             {submitFailed && error && <span>{error}</span>}
           </dt>
               { fields.map((registerDetail, index) =>
               //In the following line renderDetail is accesing Detail component.
               <Detail detailItem={registerDetail} fields={fields} index={index} key={index}/>

               )
             }

            {error && <dt className="error">{error}</dt>}
            </dl> 
            );

这是详细信息 Class 组件:

          class Detail extends Component{

                   render(){

                   const{detailItem,index,fields,isSubtotal} = this.props;

                        return(


                    <dd key={index}>
                    <br></br>
                    <button className= 'btn btn-light mr-2'
                     type="button"
                     title="Remove detail"
                     onClick={() => { fields.remove(index)
                      if(fields.length == 0 || fields.length === undefined){

                        }
                      try{
                     for(let x in fields){
                     fields.remove(index) 
                     let d = fields.selectedIndex;
                    if(fields.remove(index) && d >= 1 && d< fields.length ){
                    fields.removeAll(index);
                     }
                     }
                  }catch{console.info("deletes non numerical index")}

                      }}> Delete </button>

              <h4>DetailRegister #{index + 1}</h4>

               <Field 
                 id={`${detailItem}._id`}
                 name={`${detailItem}.quantity`}
                 component= {NumberPickerInteger}
                 placeholder= '...quantity'
                 label = "Quantity" 
                  />
          <br></br>
          <h3><b>Product</b></h3>
               <Field 
                id={`${detailItem}._id`}
                name={`${detailItem}.product.code`}
                type="number"
                component= {RenderFieldNumeric}
                placeholder='...Product's code'
               label = "Product's code" 
             />
          <Field 
           id={`${detailItem}._id`}
           name={`${detailItem}.product.name`}
           type="text"
           component= {RenderField}
           placeholder='...Product's name'
           label = "Product's name" 
         />
            <Field 
              id={`${detailItem}._id`}
              name={`${detailItem}.product.price`}
              component= {NumberPickerr}
              placeholder= '...Price'
              label = "Product's price" 
             />
         <br></br>
      <h3><b>Subtotal</b></h3>
       <Field 
          id={`${detailItem}._id`}
          name={`${detailItem}.subtotal`}
          component= {SubtotalWidget}
          placeholder= '...subtotal'
          label = "Subtotal" 
           >
            {isSubtotal}
             </Field>



            </dd>

            );

          }
       }

我想访问 BillForm 中的 ${props.detailItem}.subtotal 等详细信息。 BillForm 访问 BillDetailForm,BillDetailForm 访问 renderDetail,最后 renderDetail 访问 Detail。

问题是:如何从 BillForm 访问和使用带有动态索引 (props.index) 的数量和小计等道具?我想从 BillForm 访问 Detail 组件,按照以下顺序访问:BillForm -> BillDetailForm -> RenderDetail -> Detail

如果我没看错你的话,你似乎违背了 React 的精神。如果您的父组件想要访问一段数据,那么该数据应该从父组件开始并向下传递。这样,如果数据发生变化,它将调用组件的重新渲染并更新所有必要的组件。

其他一些建议。尽量不要在组件处理程序中包含太多逻辑,它看起来很乱并且每个渲染周期都会 运行。将其抽象为 class 上的方法,并在需要时调用它。

我的示例有望帮助您解决问题,但我建议您阅读 React 文档,因为它非常适合简单示例。 class 的使用最终将被弃用,以支持函数组件和 Hooks API.

class ParentComponent {
  state = {
    value: 0,
  }

  methodToDoSomething = (passedVal) => {
    this.setState({
      value: passVal,
    });
  }

  render() {
    const myState = this.state;
    return (
     <Component {...myState} />
    )
  }
}

class Component {
  state = {}

  render() {
    const { value , methodToDoSomething } = this.props;
    return (
     <div onClick={methodToDoSomething}>
      {value}
     </div>
    )
  }
}

// Hooks API

const ParentComponent = () => {
  
  const [stateVal, updateState] = React.useState('myString');

  return (
    <div>
      {stateVal}
      <Component passedVal={stateVal} passedHandler={updateState} />
    </div>
  )
}

const Component = ({ stateVal, passedHandler }) => {
  
  function updateMyValue() {
    passedHandler('menewvalue');
  }

  return (
    <div onClick={updateMyValue}>
     {stateValue}
    <div/>
  )
}

为了避免将大量传递给所有子组件,我建议您阅读上下文挂钩。

*** 更新 *** 上面的例子是初级的,试图回答提出的问题,解决问题的方法总是有很多。

传递 props 可能会很混乱并且会增加维护开销。大多数较大的应用程序将受益于使用状态库来管理它们的全局状态。上下文 API 是一个很好的工具,可用于包装一组内聚的组件,因此它们可以共享 data/props 而无需 prop-drilling(将 props 传递给许多子组件)。

自定义挂钩是另一种共享数据的好方法。创建一个包含您的数据和任务的任何其他方法的挂钩,并在父组件和子组件中使用这个挂钩来共享所述数据。