简体   繁体   English

如何从 function 返回 React 组件并渲染它 onClick?

[英]How can I return a React Component from a function and render it onClick?

I have an array of objects that I am looping through in my higher order component.我在高阶组件中循环遍历了一组对象。 On click I want to pass one of those objects to my component and render that component.单击时,我想将这些对象之一传递给我的组件并呈现该组件。 The problem I am having is it's unclear how to return the component and have React update the render to show that component.我遇到的问题是不清楚如何返回组件并让 React 更新渲染以显示该组件。 I've read several Stackoverflow posts on this and the problem of putting the component in the html is it passes all the items in my loop to my component instead of just the one I need onClick.我已经阅读了几篇关于此的Stackoverflow 帖子,将组件放入 html 的问题是它将我循环中的所有项目传递到我的组件,而不仅仅是我需要的那个 onClick。

The warning I'm seeing in my console is react_devtools_backend.js:3973 Warning: Functions are not valid as a React child. This may happen if you return a Component instead of <Component />我在控制台中看到的警告是react_devtools_backend.js:3973 Warning: Functions are not valid as a React child. This may happen if you return a Component instead of <Component /> react_devtools_backend.js:3973 Warning: Functions are not valid as a React child. This may happen if you return a Component instead of <Component /> Which makes sense however, I'm not sure what the proper syntax is to solve this problem. react_devtools_backend.js:3973 Warning: Functions are not valid as a React child. This may happen if you return a Component instead of <Component />但这是有道理的,我不确定解决此问题的正确语法是什么。 Below is the relevant code.下面是相关代码。

const FormGroup = ({index}) => {

  const renderSection = form => ( // I want to render this
    <AdditiveSection
      form={form}
      register={register}
      errors={errors}
    />
  );

   const addSection = form => {
     setAdditionalSection(prevState => !prevState);
     console.log('form', form);
     renderSection(form);
   };

  return (
    <section>
      <FormProvider {...methods}>
      <form onSubmit={methods.handleSubmit(onSubmit)}>
        {myForm.controls.map(form => {
          if (form.type === 'section') {
            return (
              <FormSection>
                <div className="section__label">
                  <h4>{form.label}</h4>
                </div>

                ...

                {form.button
                && (
                <FormAdd>
                  <LinkButton
                    type="button"
                    onClick={() => addSection(form)} // called here and passes my form object
                >
                  <span className="button--small">{form.button}</span>
                  </LinkButton>
                </FormAdd>
                )}

                {renderFormType(form)}
              </FormSection>
            );
          }

        })}

        // renderSection should render here outside of the loop
        {additionalSection && renderSection}


        <input type="submit" />
      </form>
    </FormProvider>
  </section>
);

Put it in state and just render.将其放入 state 并进行渲染。

const { extraSection, setExtraSection } = useState(null);

const addSection = form => {
  setExtraSection(form);
};

return (
  ...
  // renderSection should render here outside of the loop
  {extraSection}
);

The problem with your original approach is that you were not saving that element anywhere.你原来的方法的问题是你没有在任何地方保存那个元素。 You called renderSection upon click, but that just called the function without storing or displaying that code anywhere.您在单击时调用了renderSection ,但它只是调用了 function 而没有在任何地方存储或显示该代码。

Then in you render method, you again referenced rederSection .然后在您的渲染方法中,您再次引用了rederSection This is just a copy of the function, now without a parameter.这只是 function 的副本,现在没有参数。 It doesn't have any element as parameter, and it's not even called, so React is complaining that you're trying to render a function, instead of an element.它没有任何元素作为参数,甚至都没有被调用,所以 React 抱怨你正在尝试渲染一个 function,而不是一个元素。

try it试试吧

const renderSection = form => (
    
return(      
   <AdditiveSection       
       form={form}       
       register={register}       
       errors={errors}        
   />
  )
);

Just in case anyone else may be struggling with this.以防万一其他人可能正在为此苦苦挣扎。 Thanks to szaman and this article.感谢 szaman 和这篇文章。 Turns out I need to pass the section in the loop, but just pass through the data that was clicked.原来我需要在循环中传递该部分,但只传递被单击的数据。

 const addSection = form => {
   console.log('form', form);
   setAdditionalSection(form);
 };

return (
  <section>
    <FormProvider {...methods}>
    <form onSubmit={methods.handleSubmit(onSubmit)}>
      {myForm.controls.map(form => {
        if (form.type === 'section') {
          return (
            <FormSection>
              <div className="section__label">
                <h4>{form.label}</h4>
              </div>

              ...

              {form.button
              && (
              <FormAdd>
                <LinkButton
                  type="button"
                  onClick={() => addSection(form)} // called here and passes my form object
              >
                  <span className="button--small">{form.button}</span>
                </LinkButton>
              </FormAdd>
             )}

              {additionalSection && additionalSection.position === ind && (
                <AdditiveSection
                  form={additionalSection}
                  register={register}
                  errors={errors}
                />
              )}

             {renderFormType(form)}
            </FormSection>
          );
        }

      })}


      <input type="submit" />
    </form>
  </FormProvider>
</section>
);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM