0

I'm using the code below, and it does the job (for the moment). Depending on the length of the array, components are nested into each other with array-element reference as a prop. Inside the innermost element there must always be injected another element.

const arr = ['one', 'two', 'three'];
const injectedContent = <SomeContent />;

const renderNestedSections = () => {
  switch (arr.length) {
    case 1:
      return (
        <Section name={arr[0]}>
          {injectedContent}
        <Section>
      );

    case 2:
      return (
        <Section name={arr[0]}>
          <Section name={arr[1]}>
            {injectedContent}
          </Section>
        </Section>
      );

    case 3:
      return (
        <Section name={arr[0]}>
          <Section name={arr[1]}>
            <Section name={arr[2]}>
              {injectedContent}
            </Section>
          </Section>
        </Section>
      );

    default:
      return null;
  }
}

I'm struggling to make a function with algorithm that does the nesting dynamically. Any help will be much appreciated. Thanks in advance.

3 Answers 3

3

Here's something off the top of my head. Maybe there's a better/clearer way to do this, but the idea is that you iterate through each item in the array and build outward, wrapping each Section inside another Section.

To do this Array#reduce is used starting with an accumulator value of your injected content. Then you simply build upwards towards the outermost Section. Also, because we're building outwards rather than inward, we must reverse the array (keep in mind that this will mutate the array so you might want to clone it before doing this).

Here's a proof of concept using DOM rather than React.

let arr = ['one', 'two', 'three']
// Inner Content
let content = document.createElement('div')
content.innerHTML = "Hello World"

// Algorithm
let res = arr.reverse().reduce((acc, item)=>{
  let a = document.createElement('div')
  a.classList.add(item)
  a.appendChild(acc)
  return a
}, content)

document.body.appendChild(res)
div {
  padding : 10px;
  color : white;
}

.one {
  background-color: red;
}
.two {
  background-color: green;
}
.three {
  background-color: blue;
}

Here's how I think the React version would look, but I haven't tested it.

const arr = ['one', 'two', 'three'];
const injectedContent = <SomeContent />;

// Algorithm
let result = arr.reverse().reduce((acc, item)=>{
  return (
    <Section name={item}>
      {acc}
    </Section>
  )
}, InjectedContent)
Sign up to request clarification or add additional context in comments.

1 Comment

I've tested it and it works perfectly. Very compact solution, thanks again!
0

this is a recursive and declarative react component :

const RecursiveNodeWrapper = ({ layers, node }) => {
  let accumulatedNode = node;
  if (layers.length) {
    const [currentLayer, ...restLayers] = layers;
    accumulatedNode = (
      <section style={{ border: '1px solid', padding: 5 }} name={currentLayer}>
        {accumulatedNode}
      </section>
    );
    return RecursiveNodeWrapper({
      layers: restLayers,
      node: accumulatedNode,
    });
  }
  return accumulatedNode;
};

then you just need to call it like regular component:

<RecursiveNodeWrapper layers={['one', 'two']} node={<h1>hello</h1>} />

Comments

0

You can use a recursive rendering approach like

const arr = ["one", "two", "three", "four"];
const injectedContent = () => <SomeContent />;

const Section = ({ name, children }) => (
  <div>
    <div>{name}</div>
    {children}
  </div>
);

const SomeContent = () => <div>Some Content</div>;

const RecursiveContent = ({ InjectedContent, arr }) => {
  const name = arr[0];

  return (
    <Section arr={arr} name={name}>
      {arr.length > 0 ? (
        <RecursiveContent arr={arr.slice(1)} InjectedContent={InjectedContent} />
      ) : (
        <InjectedContent />
      )}
    </Section>
  );
};
const NestedSection = InjectedContent => ({ arr }) => (
  <RecursiveContent arr={arr} InjectedContent={InjectedContent} />
);

function App() {
  return (
    <div className="App">
      <NestedEle arr={arr} />
    </div>
  );
}

const NestedEle = NestedSection(injectedContent);

Working sandbox

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.