简体   繁体   中英

Could not find react-redux context value; please ensure the component is wrapped in a <Provider> although component is wrapped in a provider

I have a React on Rails app and I am getting a failure to render due to could not find react-redux context value; please ensure the component is wrapped in a <Provider> could not find react-redux context value; please ensure the component is wrapped in a <Provider> .

Component (inner content and imports omitted for brevity):

const MyPage = ({ reduxData, payloads }) => {
  const store = useReduxStore(reduxData);
  const jads = new JsonApiDataStore();
  const users = jads.sync(payloads.users);
  //custom selector
  const pathName = useSelector(selectPathName);

  return (
    <Provider store={store}>
       <div>
         {users.map((user) => (
             <li key={user.id} />
         ))}
       </div>
      <div>{pathname}</div>
    </Provider>
  );
};

MyPage.propTypes = {
  reduxData: PropTypes.shape(ReduxData).isRequired,
  payloads: PropTypes.shape({
    users: PropTypes.shape(Payload).isRequired,
  }).isRequired,
};

export default MyPage;

view(index.html.erb for this directory/controller)

<% content_for :title, "MyPage" %>

<% page = react_component_hash(
  "MyPage",
  props: {
    reduxData: redux_data,
    payloads: {
      users: serialize(
        @users,
        UserSerializer,
      ),
    }
  },
  prerender: true
) %>

<% content_for :page_styles, page["componentCss"] %>
<%= page["componentHtml"] %>

Controller Route:

  def index
    @users = User.all
    render layout: "react"
  end

in my application controller:

  def redux_data
    {
      data: {
        pathName: request.path
      },
      currentUser: serialize(current_user, CurrentUserSerializer, include: %w[company])
    }
  end
  helper_method :redux_data

(This works on other pages with a similar setup).

What am I missing?

The issue was that I was trying to use a selector in the same component that provided the Provider / context, essentially before the context was provided. Instead, I needed to use selectors only in child components / within the main component that has the <Provider /> wrapper so that the selector has access to the context.

In my case:

child component:

const ChildComponent = () => {
  const pathName = useSelector(selectPathName);
  return (
    <div>{pathname}</div>
  );
};

export default ChildComponent;

parent component:

const MyPage = ({ reduxData, payloads }) => {
  const store = useReduxStore(reduxData);
  const jads = new JsonApiDataStore();
  const users = jads.sync(payloads.users);

  return (
    <Provider store={store}>
       <div>
         {users.map((user) => (
             <li key={user.id} />
         ))}
       </div>
      <ChildComponent />
    </Provider>
  );
};

MyPage.propTypes = {
  reduxData: PropTypes.shape(ReduxData).isRequired,
  payloads: PropTypes.shape({
    users: PropTypes.shape(Payload).isRequired,
  }).isRequired,
};

export default MyPage;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM