Как переделать глубоко вложенных детей? - PullRequest
0 голосов
/ 28 апреля 2018

В следующем коде я бы хотел, чтобы все теги <p> с атрибутом "data-mini-slug" возвращались вместо тегов <input>.

Следующий код работает при возврате одного элемента <p> dom.

Как бы вы преобразовали все вложенные <p data-mini-slug="hello"> элементы в качестве входных данных, сохранив при этом структуру dom? Есть ли в React встроенное решение для этого?

function hoc(WrappedComponent) {
    return class Enhancer extends WrappedComponent {
        render() {
            const elementsTree = super.render();
            let newProps = {};
            if (elementsTree) {
                const miniSlug = elementsTree.props['data-mini-slug']
                if (elementsTree.type === "p" && miniSlug) {
                    newProps = { value: `New props is ${miniSlug}` }
                    const props = Object.assign({}, elementsTree.props, newProps)
                    return <input {...props} />
                }

            }
            return elementsTree
        }
    }
}

class Example extends React.Component {
    render() {
        // return <p data-mini-slug="deepChild" data-new-value="Deep nested child" />
        return (
            <div>
                <h1>Hoc dom element conversion</h1>
                <p data-mini-slug="child" data-new-value="Surface child" />
                <div>
                    <div>
                        <p data-mini-slug="deepChild" data-new-value="Deep nested child" />
                    </div>
                </div>
            </div>
        )
    }
}

export default hoc(Example)

Ответы [ 2 ]

0 голосов
/ 28 апреля 2018

Вы можете создать цикл, имея функцию для вызова себя в клонированном элементе.

import React from 'react'

function iterateOverChildren(children) {
    return React.Children.map(children, child => {
        if (!React.isValidElement(child)) {
            return child;
        }

        if (child.props.children) {
            child = React.cloneElement(child, {
                children: iterateOverChildren(child.props.children)
            });
        }

        return alterChild(child);
    });

}

function alterChild(child) {

    let newProps = {};
    const miniSlug = child.props['data-mini-slug']
    if (child.type === "p" && miniSlug) {
        newProps = { value: `New props is ${miniSlug}` }
        const props = Object.assign({}, child.props, newProps)
        child =  <input {...props} />
    }

    return child
}

function hoc(WrappedComponent) {
    return class Enhancer extends WrappedComponent {
        render() {
            const elementsTree = super.render();
            return iterateOverChildren(elementsTree.props.children)
        }
    }
}

class Example extends React.Component {
    render() {
        // return <p data-mini-slug="deepChild" data-new-value="Deep nested child" />
        return (
            <div>
                <h1>Hoc dom element conversion</h1>
                <p data-mini-slug="child" data-new-value="Surface child" />
                <div>
                    <div>
                        <p data-mini-slug="deepChild" data-new-value="Deep nested child" />
                    </div>
                </div>
            </div>
        )
    }
}

export default hoc(Example)
0 голосов
/ 28 апреля 2018

Решением React будет создание компонента, который будет визуализировать p или input в зависимости от некоторого свойства, например

function Comp(props){
   if(props.dataMiniSlug)
     return <p/>
   else
     return <input/>
}

Если по какой-то причине вам необходимо изменить DOM (виртуальный) так, как вы пытаетесь это сделать, вы можете рекурсивно пройти через детей с помощью React.Children API, подобного этому.

render() {
  const rootNode = super.render();
  return transform (rootNode)
}

transform(node) {
  if(node.props.children){
     return React.Children.map(element.props.children, transform)
  }      
  if (node.type === "p" && node.props['data-mini-slug'] !== undefined) {
      return <input { ...node.props, value: `New props is ${node.props['data-mini-slug']}`}/>
  }
  return node
}

Опять же, я настоятельно советую вам пересмотреть весь этот подход, иначе надеюсь, что он как-то полезен.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...