【问题标题】:enzyme shallowWrapper.setState not working for redux connected components酶 shallowWrapper.setState 不适用于 redux 连接的组件
【发布时间】:2018-09-13 18:42:34
【问题描述】:

请在标记为重复之前阅读

因此,我检查了所有建议的问题,并进行了近 2 天的研究,以找出问题背后的原因。

这是我所拥有的 -

1. 一个名为 SignIn 的组件,具有连接到 redux 存储的一些本地状态。

class SignIn extends React.Component {
  constructor(props) {
    super(props);
    this.state = { isLoading: false };
  }
  render () {
    isLoading
    ? <SomeLoadingComponent />
    : <MainSigninComponent />
  }
}
export default ConnectedSignIn = connect(mapStateToProps)(SignIn);

现在您可以看到 SignIn 的渲染输出随着本地状态的变化而变化,我打算对这两个输出进行快照测试。

于是我写了两个测试用例。

// This one is alright as it test on the default state and renders the actual SigninComponent.
test(`it renders correctly`, () => {
  const wrapper = shallow(<ConnectedSignIn {...props} />, { context: { store }});

  // .dive() because I intend to snapshot my actual SignIn component and not the connect wrapper.
  expect(wrapper.dive()).toMatchSnapshot();
});

现在,当我打算将状态更改为 { isLoading: true } 时,我会在第二次测试中像这样调用 setState。

test(`it renders the loading view on setting isLoading state to true`, () => {
  const wrapper = shallow(<ConnectedSignIn {...props} />, { context: { store }});

  console.log(wrapper.dive().state()) // returns { isLoading: false }

  // Again .dive because I want to call setState on my SignIn component

  wrapper.dive().setState({ isLoading: true });
  console.log(wrapper.dive().state()) // still returns { isLoading: false }

  // Tried the callback method to ensure async op completion
  wrapper.dive().setState({ isLoading: true }, () => {
    console.log(wrapper.dive().state()) // still returns { isLoading: false }
  });
});

所以通过上面的代码和输出,我推断浅包装器的 setState 不能正常工作,因为实际上没有更新组件的状态。

顺便提一下,

1. 我也尝试过使用 wrapper.dive().instance().setState() 正如我在某个问题中读到的那样,要更新实例的状态,这种方式会更好。 没用。

2. 我还尝试使用 wrapper.update() 和 wrapper.dive().update() 强制更新浅化组件。这个也不行。

我的依赖版本

“反应”:“16.0.0”,

"react-native": "0.50.0",

"react-redux": "^5.0.6",

“酶”:“^3.3.0”,

"enzyme-adapter-react-16": "^1.1.1",

“开玩笑”:“21.2.1”,

"react-dom": "^16.2.0"

我已经阅读了通过将组件与 redux 分开来单独测试组件的指南。我这样做了,我的测试用例运行良好,但我想知道这种行为是正常的还是错误的,如果有人成功地测试了状态更改以及渲染 redux 连接组件的更改,那么请告诉我你的方法。

【问题讨论】:

  • 奇怪,没人试过。

标签: reactjs redux react-redux jestjs enzyme


【解决方案1】:

每次您使用dive() 时,它都会创建一个新包装器,因此您的所有调用都引用了一个新包装器,而不是您更新的包装器。相反,你可以试试这个:

test(`it renders the loading view on setting isLoading state to true, () => {
  const wrapper = shallow(<ConnectedSignIn {...props} />, { context: { store }});
  const component = wrapper.dive()

  component.setState({ isLoading: true });
  console.log(component.state()) // should be {isLoading: true}
});

有关参考,请参阅Jordan Harband's answerthis Enzyme issue

【讨论】:

    【解决方案2】:

    这是不好的做法。您应该独立测试SignInConnectedSignIn

    1.创建命名导出。

    // SignIn.js
    
    export class SignIn extends React.Component {
      constructor(props) {
        super(props);
    
        this.state = {
          isLoading: false
        };
      }
    
      render() {
        const { isLoading } = this.state;
    
        return (
          (isLoading) ? <SomeLoadingComponent /> : <MainSigninComponent />
        );
      }
    }
    
    export default ConnectedSignIn = connect(mapStateToProps)(SignIn);
    

    2. 使用以下语法导入SignIn 组件。

    import { SignIn } from 'SignIn.js'
    

    请注意,我们导入 SignIn 而不是 ConnectedSignIn

    【讨论】:

    • 我不能同意更多。已经采用了上述做法,但仍然对我的问题中提到的问题的原因感到好奇。
    【解决方案3】:

    试试下面的代码。为我工作。

    const newWrapper = wrapper.dive();
    console.log(newWrapper.state()) // returns { isLoading: false };
    newWrapper.setState({
      isLoading: true
    });
    console.log(newWrapper.state()) // returns { isLoading: true }
       

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-10-14
      • 2020-10-11
      • 1970-01-01
      • 2017-11-19
      • 2019-11-01
      • 2023-03-03
      • 1970-01-01
      • 2020-11-01
      相关资源
      最近更新 更多