【问题标题】:Could not find "store" in the context of "Connect(Items)". Either wrap the root component in a <Provider> in react.js?在“Connect(Items)”的上下文中找不到“store”。将根组件包装在 react.js 中的 <Provider> 中吗?
【发布时间】:2021-10-28 18:49:56
【问题描述】:

我正在使用 React 测试库编写带有计数器的简单测试。由于提到的与 store 有关的错误,我的测试失败了。

我尝试使用不同的方法来解决它,例如创建 mockStore 并将组件包裹在 Shallow 和 Provider 周围。我也尝试在 index.js 中创建商店,但我已经导入了 store。我似乎无法指出问题所在。

如果有人能告诉我如何解决它,我将不胜感激。

这是我的代码:

Store.js:

import {createStore, applyMiddleware} from 'redux'
import thunk from 'redux-thunk'
import {composeWithDevTools} from 'redux-devtools-extension'


import rootReducer from './reducers'

const initialState = {

}



const middleware = [thunk]

const store = createStore(rootReducer, initialState, composeWithDevTools(applyMiddleware(...middleware)))

export default store;

index.js:

import "./index.css";
import reportWebVitals from "./reportWebVitals";
import { Provider } from "react-redux";
import store from "./store/store";
import App from "./App";
import { BrowserRouter  } from "react-router-dom";



ReactDOM.render(
  <BrowserRouter>
    <Provider store={store}>
      <App />
    </Provider>
  </BrowserRouter>,
  document.getElementById("root")
);
 reportWebVitals();

Bill.test.js:

import { screen, fireEvent, act } from "@testing-library/react";
import BillList from "../BillList";
import Adapter from 'enzyme-adapter-react-16'
import configureMockStore from "redux-mock-store";
import { shallow, configure  } from "enzyme";
import { Provider } from "react-redux";

const mockStore = configureMockStore();
const store = mockStore({});


configure({adapter: new Adapter()});
describe("<BillList />", () => {
  // will display 1 by default because there will be already an item when the page renders
  test("display counter text", () => {
    shallow(
        <Provider store={store}>
            <BillList />
        </Provider>
     
        ) 

    expect(screen.queryByTestId("counter-text")).toBe("1");
  });

  // Button increments the price value by +1
  test("increment counter", () => {
   shallow(
   <Provider store={store}>
       <BillList />
       </Provider>

   ) 

    const btnIncrement = screen.queryByTestId("btn-increment");
    fireEvent.click(btnIncrement);

    expect(screen.queryByTestId("counter-text")).toBe("2");
  });

  // Button decrements the price value by -1

  test("decrement counter", () => {
    shallow(
        <Provider store={store}>
            <BillList />
        </Provider>
     
        ) 
    const btnDecrement = screen.queryByTestId("btn-decrement");
    fireEvent.click(btnDecrement);
    

    expect(screen.queryByTestId("counter-text")).toHaveTextContent("1");
  });

});

BillList.js:

import React, { useState } from "react";
import "./Bill.css";
import { Link, useParams, Switch, Route } from "react-router-dom";
import { connect,} from "react-redux";

import { getItems } from "../store/actions/itemsActions";

function BillList({ items }) {
  const [counter, setCounter] = useState(1);
  const { id } = useParams();
  var ust = parseFloat(0.18);

  function Display(props) {
    return <label style={{ marginLeft: ".5rem" }}>{props.message}</label>;
  }

  return (
    <div className="bills">
      <div
        className="main-title"
        style={{
          textAlign: "center",
          justifyContent: "center",
          alignItems: "center",
          fontSize: 14,
        }}
      >
        <h1>Bakery</h1>
        <h1>Company Gbr</h1>
        <h1>Oranienburger Straße 120</h1>
        <h1>10119 Berlin</h1>
      </div>

      <div className="bills-container">
        {/* pass in the details  */}
        <div className="item-list">
          {items &&
          items.items
            .filter((item) => item.id === Number(id))
            .map((item) => (
              <React.Fragment key={item.id}>
                <div className="bill-time">
                  <div className="bill">
                    <h4>
                      {" "}
                      <strong>Bill: </strong>
                      {item.billNumber}
                    </h4>
                  </div>

                  <div className="time">
                    <h4>
                      {" "}
                      <strong>Time: </strong>
                      {item.created_datetime}
                    </h4>
                  </div>
                </div>
                <div className="lines-time">
                  ------------------------------------------------------------------------------------------
                </div>

                {/* Counter  */}
                <div className="price-total">
                  <div className="head-title">
                    <div className="title">
                      <h3>
                        {" "}
                        <strong>Title: {item.title} </strong>
                      </h3>
                    </div>
                    <div className="counter" data-testid="counter-text">
                      <strong>
                        <Display  message={counter} />x
                      </strong>
                    </div>
                    <div className="lines">------------</div>
                  </div>

                  <div className="increase">
                    <button onClick={() => setCounter(counter + 1)} data-testid="btn-increment">+</button>
                  </div>
                  <div className="decrease">
                    <button onClick={() => setCounter(counter - 1)} data-testid="btn-decrement">-</button>
                  </div>

                  {/* Price and total */}

                  <div className="price">
                    <h4>
                      <strong>Price: {parseFloat(item.price).toFixed(2)}€ </strong>
                    </h4>
                  </div>
                  <div className="a">A</div>

                  <div className="total">
                    <h4>Total: </h4>
                  </div>
                  <div className="total-price">
                    {parseFloat(item.price * counter).toFixed(2)}€
                  </div>
                  <div className="given">
                    <h4>Given: (iZettle)</h4>
                  </div>
                  <div className="given-price">
                    {parseFloat(item.price * counter).toFixed(2)}€
                  </div>
                  <div className="lines-taxes">
                    -------------------------------------------------------------------------------
                  </div>
                  <div className="gross">
                    <h4>
                      <strong>gross</strong>
                    </h4>
                  </div>
                  <div className="gross-price">{((parseFloat(item.price) * counter)).toFixed(2)}€</div>
                  <div className="taxes">
                    <h4>USt.%</h4>
                  </div>
                  <div className="percent">A=7%</div>
                  <div className="ust">
                    <h4>USt.</h4>
                  </div>
                  <div className="ust-percent">{(ust * counter).toFixed(2)} €</div>
                  {/* net - the USt */}
                  <div className="net">
                    <h4>net</h4>
                  </div>
                  <div className="net-result">
                   
                    {(parseFloat(item.price) * counter - parseFloat(0.18 * counter)).toFixed(2)} €
                   
                  </div>
                </div>
              </React.Fragment>
            ))}
        </div>
        {/* Paragraph */}
        <div className="terminal">
          <p> Table:  Counter</p>
          <p> Terminal:  Terminal 1</p>
          </div>
       
        <div className="TSE-Transaktion ">
          <p>
            TSE-Transaktion 
          </p>
          <p>TSE-Signatur-Nr. </p>
          <p>
          TSE-Start 
          </p>
          <p>
          TSE-Stop 
          </p>
          <p>
          TSE-Seriennummer
          </p>
          <p>
          TSE-Zeitformat
          </p>
          <p>
          TSE-Signatur 
          </p>
          <p>
          TSE-Hashalgorithmus
          </p>
          <p>
          TSE Status 
          </p>
        </div>


        <div className="right-side">
          <p>
          1831
          </p>
          <p>
          98009
          </p>
          <p>
          2020-04-21T09:29:38.00000Z
          </p>
          <p>
          2020-04-21T09:29:50.00000Z
          </p>
          <p>
          5f2897cc074ae841330658eadd324661159f53b7ffd29215
          </p>
          <p>
          utcTime
          </p>
          <p>
          bXkPffFOcetbFokYrOqr/7EYrAc0PH6r
          </p>
          <p>
          ecdsa-plain-SHA256
          </p>
          <p>
          In evaluation
          </p>

        </div>
      

        <div className="de11">
        <p>Ust-Id: DE11111111</p>
        </div>
        





        {/* Button */}
      </div>

      <div className="button-path">
        <Link data-testid="analyse-receipt-path" to="/">
          <div className="button">
            <button data-testid="analyse-receipt"  className="main-button">Analyse Receipt</button>
          </div>
        </Link>
      </div>

      <Switch>
        <Route path="/bills/:id" />
      </Switch>
    </div>
  );
}

const mapStateToProps = (state) => {
  return {
    items: state.items,
  };
};

const mapDispatchToProps = (dispatch) => {
  return {
    getItems: () => dispatch(getItems()),
  };
};

export default connect(mapStateToProps, mapDispatchToProps)  (BillList);



 

【问题讨论】:

  • 你遇到了什么错误?你正在测试BillList 组件,显示代码
  • 我收到此错误在“Connect(Items)”的上下文中找不到“store”。要么将根组件包装在 ** 中,我知道这是因为商店,但我已经将 ** 组件包装在 中。 ..我有点困惑,一切似乎都到位了,我更新了代码,请检查一下!
  • 错误提到了Connect(Items),但我在任何地方都没有看到Items 组件。你有这样的组件。另外,当你只使用 BillList 组件(非连接版本)时,它工作正常吗?

标签: javascript reactjs redux react-redux react-testing-library


【解决方案1】:

您正在测试该组件,因此您无法访问 Provider,因为它是父组件。您可以创建一个自定义包装器,以便您可以在每个测试中使用 Redux。使用下面的你将使用reduxRender 而不是标准的render

import { render} from '@testing-library/react'
import { Provider as ReduxProvider } from 'react-redux'
import store from './whereverYourStoreIs/store'

/** To be used whenever Redux is referenced */
const ReduxWrapper = ({ children }) => (
    <ReduxProvider store={store}>
      {children}
    </ReduxProvider>
)

/**Render used for Redux */
const reduxRender = (ui, options) =>
  render(ui, { wrapper: ReduxWrapper, ...options })

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-11-27
    • 2021-10-19
    • 1970-01-01
    • 1970-01-01
    • 2017-04-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多