Как получить доступ к состоянию на вложенном компоненте React, завернутом HOC?
Я использую Enzyme, и мы можем использовать пример компонента, приведенный в документации, в качестве основы для моего вопроса.
Предположим, что этот компонент <Foo/>
использует компонент <Link>
из ReactRouter, и поэтому нам нужно обернуть его в <MemoryRouter>
для тестирования.
В этом и заключается проблема.
it('puts the lotion in the basket', () => {
const wrapper = mount(
<MemoryRouter>
<Foo />
</MemoryRouter>
)
wrapper.state('name') // this returns null! We are accessing the MemoryRouter state, which isn't what we want!
wrapper.find(Foo).state('name') // this breaks! state() can only be called on the root!
})
Таким образом, не совсем уверен, как получить доступ к состоянию локального компонента при использовании <MemoryRouter>
.
Возможно я выполняю невежественный тест? Является ли попытка получить/установить состояние компонента плохой практикой при тестировании? Я не могу себе это представить, так как Enzyme имеет методы для получения/установки состояния компонента.
Просто не уверен, как можно получить доступ к внутренним компонентам компонента, <MemoryRouter>
в <MemoryRouter>
.
Любая помощь будет принята с благодарностью!
Ответы
Ответ 1
Итак, кажется, что с помощью последней версии Enzyme существует потенциальное исправление этой проблемы доступа к состоянию дочернего компонента.
Скажем, имеем <Foo>
(обратите внимание на использование React Router <Link>
)
class Foo extends Component {
state = {
bar: 'here is the state!'
}
render () {
return (
<Link to='/'>Here is a link</Link>
)
}
}
Примечание. Следующий код доступен только в Enzyme v3.
Пересмотр тестового кода, теперь мы можем написать следующие
it('puts the lotion in the basket', () => {
const wrapper = mount(
<MemoryRouter>
<Foo />
</MemoryRouter>
)
expect(wrapper.find(Foo).instance().state).toEqual({
bar: 'here is the state!'
})
})
Используя wrapper.find(Child).instance()
, мы можем получить доступ к состоянию Child
, даже если это вложенный компонент. В предыдущих версиях Enzyme мы могли получить доступ только к instance
в корне. Вы также можете вызвать функцию setState
в обертке Child
!
Мы можем использовать аналогичную модель с нашими неглубоко оцениваемыми тестами
it('puts the lotion in the basket shallowly', () => {
const wrapper = shallow(
<MemoryRouter>
<Foo />
</MemoryRouter>
)
expect(wrapper.find(Foo).dive().instance().state).toEqual({
bar: 'here is the state!'
})
})
Обратите внимание на использование dive
в неглубоком тесте, который может быть запущен на одном, не DOM node и вернет node, мелкорежущий.
Refs:
Ответ 2
Думаю, это может быть полезно для вас, ребята, так как я наткнулся на это и исправлю.
В моем случае у меня есть компонент, который связан с Redux.
class ComponentName extends Component {
...
}
export default connect(
mapStateToProps,
{
...
}
)(ComponentName );
connect(), очевидно, является компонентом HOC. Итак, как нам получить доступ к "ComponentName" здесь?
Очень просто:
component
.find(ComponentName)
.children()
.first()
.props() // returns ComponentName props