0

I am trying to use Context in my form, so i have same component for edit and create form. The only difference edit form will have the pre-filled values.

I am adding a sample snippet of the workflow, the problem is here i am getting the props as empty object but i passing the context value on the clone element.

App.js

<Container {...props}>
  <Fragment>
    <Form />
    <div>
      Latest Details
    </div>
  </Fragment>
</Container>

Container.js

const Container = (props) => {
  const ContainerContext = createContext({ ...defaultState, ...props });
  return (
    <ContainerContext.Provider value={{ ...defaultState, ...props }}>
      <ContainerContext.Consumer>
        {(value) => {
          return React.Children.map(props.children, (child) => {
            return React.cloneElement(child, { ...props, ...value });
          });
        }}
      </ContainerContext.Consumer>
    </ContainerContext.Provider>
  );
}

Form.js

const Form = (props) => {
  console.log(props) // getting empty object
  return 'form'
}

Any help is appreciated

Update

App.js

<Container {...props}>
  <Fragment>
    <TopContainer>
      <TopData />
    </TopContainer>
    <MiddleContainer>
      <Form />
    </MiddleContainer>
    <LowContainer>
      <LowData />
    </LowContainer>
  </Fragment>
</Container>;
dev
  • 814
  • 10
  • 27

2 Answers2

1

Container direct children is React.Fragment and not your Form, so you passing props to React.Fragment element.

To check it, just log the props.children in Container component.

// Remove React.Fragment
<Container {...props}>
  <Form />
</Container>
Dennis Vash
  • 50,196
  • 9
  • 100
  • 118
  • If i remove the fragment, the form is repeating multiple times – dev Nov 04 '20 at 11:51
  • i have updated the App.js in the question, i have multiple level, so how can i easily get the props everywhere. I hope you got the idea by seeing the hierarchy with a better example. I tried removing the Fragment but its repeating – dev Nov 04 '20 at 11:59
  • When there is a single component it's coming, i have updated the App.js structure in the question, if it was single i could use cloneElement directly since i had multiple elements using React.Chidlren.map. So is there a way to solve this ? – dev Nov 04 '20 at 12:11
  • You asked a question, I answered, and then you edit your question to a new one – Dennis Vash Nov 04 '20 at 12:18
  • Just write a recursion function with `Children.map` – Dennis Vash Nov 04 '20 at 12:18
  • function recursiveMap(children, fn) { return React.Children.map(children, (child) => { if (!React.isValidElement(child)) { return child; } if (child.props.children) { child = React.cloneElement(child, { children: recursiveMap(child.props.children, fn), }); } return fn(child); }); } {() => recursiveMap()} – dev Nov 04 '20 at 12:38
  • confused how to pass the values gets from the context, i have added this way, can you correct me on what i am doing here – dev Nov 04 '20 at 12:38
  • {(value) => recursiveCloneChildren(props.children, value)} function recursiveCloneChildren(children, value) { return React.Children.map(children, (child) => { var childProps = {}; if (React.isValidElement(child)) { childProps = { ...value }; } childProps.children = recursiveCloneChildren(child.props.children); return React.cloneElement(child, childProps); }); } – dev Nov 04 '20 at 14:26
  • I have tried this way, the props are not getting and when i debug one per after its showing as undefined. – dev Nov 04 '20 at 14:26
  • @ Dennis, thanks for the info of recursion, i was able to see the child components with the props. Added the code also, If any improvements needs to do, kindly let me know – dev Nov 04 '20 at 15:22
  • Hi @Dennis Vash, I had one doubt regarding on this question https://stackoverflow.com/questions/70063149/event-timeline-with-animation. If you can help me on this it will be really helpful, many thanks – dev Nov 23 '21 at 10:53
0

As Denish suggested i have tried this way. And this way i was able to solve it.

function recursiveCloneChildren(children, value) {
    return React.Children.map(children, (child) => {
      var childProps = {};
      if (React.isValidElement(child)) {
        childProps = {
          ...value,
        };
      }
      childProps.children = recursiveCloneChildren(
        child.props.children,
        childProps
      );
      return React.cloneElement(child, childProps);
    });
  }


 <ContainerContext.Consumer>
        {(value) => recursiveCloneChildren(props.children, value)}
 </ContainerContext.Consumer>
dev
  • 814
  • 10
  • 27