Teraz w zasadzie nic nowego nie stworzymy (no prawie). Poprawimy tylko kardynalny błąd, jakim jest przekazywanie argumentu jako tablicy. Do dzieła!

Nasz poprzedni createElement:

function createElement_v6(type, attributes={}, children=[]){
    const childElements = [...children].map(
        child =>
            child instanceof Object
                ? child
                : createElement_v6("li", {
                    textContent: child
                }) 
              );

            return {
                    type,
                    children: childElements,
                    props: Object.assign({ children: childElements }, attributes)
            }
}

Przykład użycia 1:

let v6 = createElement_v6("ul", {class: "my-list"}, children = [
    "PHP", 
    "JAVASCRIPT",
    'C#'
   ]
);

console.log(v6);


// Object { 
//     type: "ul",
//      children: (3) [
//         0: Object { 
//             type: "li", 
//             children: [], 
//             props: Object { children: [], textContent: "PHP" }
//          }
// ​​
//         1: Object { type: "li", children: [], props: {…} }
// ​​
//         2: Object { type: "li", children: [], props: {…} }
//      ], 
//      props: {
//         children: Array(3) [ {…}, {…}, {…} ],
// ​​        class: "my-list"
//      } }

Przykład użycia 2:

let v6_2 = createElement_v6("ul", {class: "my-list"}, children = [
    "PHP", 
    "JAVASCRIPT",
     {
        type: "li",
        children: [],
        props: {
            children: [],
            textContent: "PHP"
        }
     }
   ]
);

console.log(v6_2);

// Object { 
//     type: "ul",
//      children: (3) [
//         0: Object { 
//             type: "li", 
//             children: [], 
//             props: Object { children: [], textContent: "PHP" }
//          }
// ​​
//         1: Object { type: "li", children: [], props: {…} }
// ​​
//         2: Object { type: "li", children: [], props: {…} }
//      ], 
//      props: {
//         children: Array(3) [ {…}, {…}, {…} ],
// ​​        class: "my-list"
//      } }

Jak nie rozumiemy, to musimy przerobić lekcje poprzednie + lekcję o variadic functions. Bo takiej funkcji chcemy, a nie tablicy.

I tak jest nieźle – wykonujemy map na kopii tablicy z argumentów. Ale my chcemy mieć …args, które poddajemy wzorcowi concat+map:

function createElement_v7(type, attributes={}, ...children){
    const childElements = [...children].map(
        child =>
            child instanceof Object
                ? child
                : createElement_v7("li", {
                    textContent: child
                }) 
              );

            return {
                    type,
                    children: childElements,
                    props: Object.assign({ children: childElements }, attributes)
            }
}

W sumie koniec końców obyło się bez concat, spread i rest wystarczył… Oto użycie:

let v7 = createElement_v7("ul", {class: "my-list"}, 
    "PHP", 
    "JAVASCRIPT", 
    {
        type: "li",
        children: [],
        props: {
            children: [],
            textContent: "C#"
        }
     }
    );
    
console.log(v7);

// Object { 
//     type: "ul",
//      children: (3) [
//         0: Object { 
//             type: "li", 
//             children: [], 
//             props: Object { children: [], textContent: "PHP" }
//          }
// ​​
//         1: Object { type: "li", children: [], props: {…} }
// ​​
//         2: Object { type: "li", children: [], props: {…} }
//      ], 
//      props: {
//         children: Array(3) [ {…}, {…}, {…} ],
// ​​        class: "my-list"
//      } }

Sam mam niezły mindfuck od tego wszystkiego, a jeszcze jest to programowanie nieobiektowe, JS-specific i DOM-specific, więc można oczopląsu dostać i żadnego ratunku nie ma.

ServiceLocator to przy tym pikuś. Collection – Composable Query – Queried Collection to przy tym pikuś. Ale gdyby ludzie tak się poddawali, albo korzystali tylko z raz utworzonych wzorców to nie byłoby ani Reacta, ani Hooków.

Tym niemniej polecam małą przerwę i na spokojnie ogarnięcie wszystkiego.