React:直接导入子组件而不是作为依赖项传入是不好的做法吗?

时间:2018-01-22 16:41:34

标签: reactjs testing react-redux enzyme

我可能在想这个,但我很好奇,如果直接导入子组件是关于耦合和测试的坏习惯。

下面是一个简单的例子:

import Header from './header.jsx';

class Widget extends React.Component {
    render() {
        return (
            <div>
                <Header></Header>
                <div>{this.props.importantContent}</div>
            </div>
        )
    }
}

对我而言,WidgetHeader之间似乎存在耦合。关于测试,我在测试Header组件时没有看到模拟Widget组件的简单方法。

其他较大的React应用程序如何处理这样的案例?我应该将Header作为道具传递吗?如果使用react-redux,我可以使用下面的Connect方法注入标头以减少样板。听起来好吗?

import { connect } from 'react-redux';
import Header from './header.jsx';

class Widget extends React.Component {
    render() {
        return (
            <div>
                {this.props.header}
                <div>{this.props.importantContent}</div>
            </div>
        )
    }
}

const mapStateToProps = state => {
  return {
    header: Header
  }
}

export default connect(mapStateToProps)(Widget)

我感兴趣的是做社区一般做的事情。我看到一个解决方案是使用浅层渲染来测试组件的主要部分,而不是像Enzyme那样测试子组件。

思想或其他想法?

2 个答案:

答案 0 :(得分:1)

将元素/组件作为道具传递是一个好主意。拥有默认道具也是一个好主意:

const Widget = ({
  header = <div>Default Header.. </div>,
  content = <div>Default Content.. </div> 
}) =>
  <div>
    {header}
    {content}
  </div>

然后在你的应用中的其他地方:

<Widget header={<Header title="Foo" />} content="content from props" />

无需使用connect

进行注射

如果你想与道具交互/将数据发送回父母,你也可以传递一个组件,而不仅仅是一个元素:

const Widget = ({
  Header = props => <div>Default Header.. </div>,
  Content = props => <div>Default Content.. </div> 
}) =>
  <div>
    <Header />
    <Content />
  </div>

其他地方:

<Widget Header={Header} Content={props => <Content />} />

答案 1 :(得分:1)

只要组件始终呈现相同的内容,它就可以直接呈现为子项而不是父项。

如果Component的所有其他部分保持不变并且只有Header可以在页面之间有所不同,那么你实际上可以将它实现为HOC而不是将其作为道具传递

const MyCompFactory = ({CustomHeader = DefaultHeader}) => {
  return class Widget extends React.Component {

        render() {
            return (
                <div>
                    <CustomHeader/>
                    <div>{this.props.importantContent}</div>
                </div>
            )
        }
    }

}

并像

一样使用它
const CustomComponent = MyCompFactory({CustomComponent: Header})

只要在您的情况下进行测试,您可以浅显示您的组件,然后搜索Header组件是否呈现类似

import Header from 'path/to/header'

const component = shallow(
    <Widget {...customProps}/>
)

test('test' , () => {
   expect(component.find(Header).exists()).toBe(true)
})