Как я могу получить доступ к вложенному компоненту в реакции от родительского компонента? - PullRequest
0 голосов
/ 16 февраля 2020

Я хочу получить доступ к вложенному компоненту из родительского компонента.

Это Bill 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 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>

            );

          }
       }

I хотите получить доступ, например, ${props.detailItem}.subtotal, который подробно из BillForm. BillForm обращается к BillDetailForm, BillDetailForm обращается к renderDetail, а последний renderDetail получает доступ к Detail.

Вопрос заключается в следующем: как получить доступ и использовать реквизиты, такие как количество и промежуточный итог, с динамическим c index (props.index) из BillForm? Я хочу получить доступ к компоненту Detail из BillForm, соблюдая следующую последовательность действий при доступе к заказу: BillForm -> BillDetailForm -> RenderDetail -> Detail

1 Ответ

0 голосов
/ 16 февраля 2020

Если я правильно понимаю, что вы говорите, похоже, вы идете вразрез с идеей Реакта. Если ваш родительский компонент хочет получить доступ к части данных, то эти данные должны начинаться с родительского компонента и передаваться вниз. Таким образом, если данные изменятся, он вызовет повторную визуализацию компонентов и обновит все необходимые компоненты.

Некоторые другие рекомендации. Постарайтесь не иметь так много логики c внутри ваших обработчиков компонентов, это выглядит грязно и будет запускаться каждый цикл рендеринга. Абстрагируйте это в метод класса и вызывайте его при необходимости.

Мой пример, надеюсь, поможет вам в вашей проблеме, но я рекомендую прочитать документацию React, поскольку она очень хороша для простых примеров. Использование класса в конечном итоге будет признано устаревшим в пользу компонентов функций и API-интерфейса Hooks.

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/>
  )
}

Чтобы не передавать партии всех дочерних компонентов, я бы порекомендовал прочесть на Context Hook.

...