查找嵌套在html元素中的React组件

时间:2018-02-01 14:19:14

标签: javascript html reactjs

我正在尝试编写可重用的组件,以便在将来的项目中使用。只要组件“T”没有嵌套在html元素中,我编写的代码就可以工作。

我写的localize.js如下;

import React, { Component } from 'react';

const Localizeit = (props) => {
  let textWithLanguageProps = React.Children.map(props.children, function(child) {
    let { s } = child.props; 
    if (React.isValidElement(child)){
        return React.cloneElement(child, {lang : props.data[s]} );
      } 
      return child;
  });
  return (
    <div>
      {textWithLanguageProps}
    </div>
  )
}

const T = ({lang}) => (
  <span>{lang}</span>
)


export { Localizeit , T};

在我使用我的翻译组件的组件中,我将所有要在其中呈现的内容包装起来,然后组件检查是否存在有效的react元素。如果有,那么他们用道具和字符串一起渲染。只要组件没有嵌套,这就可以工作。我无法找到解决这个问题的方法。我是否必须深入检查html元素是否具有嵌套的反应组件?

demo.js如下;

import React, { Component } from 'react'
import { render } from 'react-dom'
import { Localizeit, T } from './localize';

const en = {
            hello: "hello world",
            works: "it works weirdly enough"
           }

const es = {
            hello: "hola mundo",
            works: "funciona bastante raro"
           }
const tr = {
            hello: "merhaba dunya",
            works: "garip bir sekilde calisiyor."
           }


class Demo extends Component {
  constructor(props) {
    super(props);
    this.state = {
      lang: en
    }
  }
  render() {
    return (
      <div>
        <Localizeit data={this.state.lang}>
          <button onClick={() => this.setState({ lang: en })}>en</button>
          <button onClick={() => this.setState({ lang: tr })}>tr</button>
          <button onClick={() => this.setState({ lang: es })}>es</button>
          <h1>react-localizeit Demo</h1>
          <T s="hello" />
          <br />
          <p>Following doesn't work</p>
          <span><T s="works" /></span>
        </Localizeit>
      </div>
    )
  }
}

render(<Demo />, document.getElementById('root'))

可以找到工作演示here

2 个答案:

答案 0 :(得分:1)

我有渲染道具版的工作原型。在这里,我可以按照自己的意愿进行嵌套,但它仍然有效。

const en = {
  hello: "hello world",
  works: "it works weirdly enough"
};
const es = {
  hello: "hola mundo",
  works: "funciona bastante raro"
};
const tr = {
  hello: "merhaba dunya",
  works: "garip bir sekilde calisiyor."
};
const data = { en, es, tr };

class Localize extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      lang: props.initialLanguage || "en"
    };
  }
  render() {
    if(!this.props.data) return null;

    return this.props.render({
      selectedLanguage: this.state.lang, 
      onChange: lang => this.setState({ lang }),
      dict: (this.props.data[this.state.lang]) || {}
    });
  }
}

const App = () => (
  <Localize
    data={data}
    initialLanguage="en"
    render={({ dict, onChange, selectedLanguage}) => (
      <div>

        <h1>localize</h1>
        <div>You have selected: {selectedLanguage}</div>

        <button onClick={() => onChange("en")}>en</button>
        <button onClick={() => onChange("es")}>es</button>
        <button onClick={() => onChange("tr")}>tr</button>
        <div>{dict.hello}</div>
        <div>{dict.works}</div>
        <div>
          <div>
            <span>{dict.hello}</span>
          </div>
          <div>
            <span>{dict.works}</span>
          </div>
        </div>
      </div>
    )}
  />
);

ReactDOM.render(<App />, document.querySelector("#root"));

沙盒示例 https://codesandbox.io/s/218vx9oo5r

答案 1 :(得分:0)

React组件类型是一个函数,而不是一个常规组件,它是一个字符串。

这是我的解决方案:

function buildChildrenWithProps(children, props) {
    return React.Children.map(children, (child) => {

        // if not a valid Component
        if (typeof child.type !== 'function') {
            return child;
        }

        return React.cloneElement(child, Object.assign({}, child.props, props));
    });
}

用法是:

render(){
    const _children = buildChildrenWithProps(this.props.children, {/*props*/});

    return (
       <div>{_children}</div>
    );
}