使用< Provider>通过上下文传递商店在基于connect()的方案中不起作用 [英] Passing store through context with <Provider> not working in connect() based scenario

查看:40
本文介绍了使用< Provider>通过上下文传递商店在基于connect()的方案中不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

摘要-我的问题的最初原因实际上是一个错字:由于大写的'G'而不能正常工作.

Summary - the initial cause of my question was actually a typo: it wasn't working due to a capital 'G'.

但是,善良的回答者不仅解决了打字错误,而且还解决了我所采用的方法中的错误前提-如果您也使用提供方通过connect传递存储,则他们的答案与您相关.我已经更新了问题的标题以反映这一点.

However, the kind answerers addressed not only the typo, but the wrong premise in the approach I was taking - if you too are passing store using Provider and using connect, their answers are relevant to you. I have updated the title of the question to reflect this.

我正在尝试遵循很棒的redux视频,但是使用来自react-redux的< Provider> 传递到商店中而感到悲痛.

I am trying to follow the instructions in the awesome redux videos , but have come to grief with passing down the store using <Provider> from react-redux.

我有一个根组件:

export default class Root extends Component {
   render() {

      const { store } = this.props

      return (
         <Provider store={store}>
            <div>
               <ReduxRouter />
               <DevTools />
            </div>
         </Provider>
      )
   }
}

还有一个尝试使用存储的演示组件:

And a presentation component trying to use store:

const ProjectsSummary = (props, {store}) => {
   const state = store.GetState();
   const { projects } = state;

   return (
      <div className="home-projects col-md-10">
          <h3>Projects</h3>
          <ul>
              { projects.map(p => <li key={p.id}>{p.contract.client}</li>) }
          </ul>
      </div>
   )
}

ProjectsSummary.contextTypes = {
   store: React.PropTypes.object
};

class Home extends BasePage {

   render() {
      return (
         <div className="home-page container-fluid">
             {super.render()}
             <HomeLeftBar/>
             <HomePageHeader/>
             <ProjectsSummary/>
         </div>
      )
   }
    }

export default connect()(Home)

我收到未捕获的TypeError:store.GetState不是函数"

I get "Uncaught TypeError: store.GetState is not a function"

这家商店是从这里来的:

The store is coming from here:

import configureStore from './store/configureStore'

const store = configureStore({
   security:{
      jwt: 'mock'  // Mock data supplied below: only loaded when this is set.
   }, 
   projects: [
      {
            // elided for brevity
      }
   ]
})

/**
 * Main application render method that attaches it
 * to the HTML page.
 */
render(
   <Root store={store}/>,
   document.getElementById('app')
)

,并在此处创建:

export default (initialState) => {
   const store = createDevStore(initialState)

   if (module.hot) {
      // Enable Webpack hot module replacement for reducers
      module.hot.accept(['../../common/reducers', '../reducers'], () => {
         const nextRootReducer = require('../../common/reducers')
         const nextBrowserReducers = require('../reducers')
         store.replaceReducer(nextRootReducer(nextBrowserReducers))
      })
   }

   return store
}

function createDevStore(initialState){
   if(initialState && initialState.security && initialState.security.jwt === 'mock')
      return mockCreateStore(rootReducer(browserReducers), initialState)
   else
      return finalCreateStore(rootReducer(browserReducers))
}

const mockCreateStore = compose(
   reduxReactRouter({routes, createHistory}),
   applyMiddleware(createLogger()),
   DevTools.instrument()
    )(createStore)

(不是我的代码,一个支持React Native和浏览器客户端的框架,我将在其中开始工作)

(Not my code, a framework that supports react native and browser client, which I am starting work in)

我想念什么?

我正在复制视频中的内容-请注意,使用connect()不会包装" AddTodo组件:

I am copying this from the video - note that AddTodo component is not "wrapped" using connect():

const AddTodo = (props, { store }) => {
  let input;

  return (
    <div>
      <input ref={node => {
        input = node;
      }} />
      <button onClick={() => {
        store.dispatch({
          type: 'ADD_TODO',
          id: nextTodoId++,
          text: input.value
        })
        input.value = '';
      }}>
        Add Todo
      </button>
    </div>
  );
};
AddTodo.contextTypes = {
  store: React.PropTypes.object
};

推荐答案

此答案是正确的,但我想澄清一些事情.

This answer is correct but I would like to clarify a few things.

您似乎对表示和容器组件以及 connect()的角色有很多困惑.我建议您再次观看相关的视频,并确保您观看到了最后.

You seem to have a lot of confusion around presentational and container components, and the role of connect() there. I suggest you to watch the relevant videos again, and make sure you watch them to the very end.

  1. 确实, store.GetState()不是有效的方法; store.getState()是.
  2. 如果您手动使用 store.getState() ,您还必须在某处使用 store.subscribe(),这样您将始终获得最大收益最近状态.您从视频粘贴的示例 AddTodo 组件无法单独使用-仅在视频中有效,因为我们在视频服务器上有一个 store.subscribe(render)最高.
  3. 本课程后面的视频讨论了如何从顶部进行重新渲染变得麻烦,在这一点上,我们介绍了容器组件.稍后,我们展示了使用 connect()生成容器组件比手工编写要容易得多,在这种情况下, connect()负责订阅商店.
  4. 在您的情况下,仅将 Home 包装在 connect()中是无效的. connect()会生成一个订阅商店的容器组件,但是如果您未指定 mapStateToProps 参数,它甚至不会订阅该商店.使用 connect()是使用 store.getState() store.subscribe() contextTypes的有效替代方法手动.两者都不要在某些东西上使用 connect()并调用 store.getState()或指定 contextTypes .
  1. Indeed, store.GetState() is not a valid method; store.getState() is.
  2. If you use store.getState() manually you have to also use store.subscribe() somewhere so you always get the most recent state. The example AddTodo component you pasted from the video will not work by itself—it only worked in the video because we had a store.subscribe(render) at the very top.
  3. Later videos in the course discuss how re-rendering from the top can get cumbersome, at which point we introduce container components. And later we show that it’s easier to generate container components using connect() than write them by hand—in this case, connect() takes care of subscribing to the store.
  4. Merely wrapping Home in connect() in your case has no effect. connect() generates a container component that subscribes to the store, but it won’t even subscribe to the store if you don’t specify the mapStateToProps argument. Using connect() is an efficient replacement for using store.getState(), store.subscribe() and contextTypes manually. It never makes senses to both use connect() on something and call store.getState() or specify contextTypes.

所以,再次总结一下:

  • store.getState() store.subscribe()是低级API.如果决定使用它们,则必须将它们一起使用.一个没有另一个是没有道理的.

  • store.getState() and store.subscribe() are low-level APIs. You have to use them together if you decide to use them; one without the other doesn’t make sense.

connect()负责调用 getState() subscribe()并将必要的信息传递给子级通过道具为您准备组件.如果使用 connect(),则永远不需要 store.getState() store.subscribe() contextTypes . connect()的全部要点是将它们抽象化.

connect() is what takes care of calling getState() and subscribe() and passing the necessary information to child components via props for you. If you use connect() you never need store.getState(), store.subscribe(), or contextTypes. The whole point of connect() is to abstract them away.

这些课程将教您所有这些工具,以告诉您没有魔术.但是,通常您不应该在实际应用中使用 store.getState() store.subscribe().除非您有非常特定的原因访问低级API,否则您应该几乎完全使用 connect().

The lessons teach you all of these tools to show you that there is no magic. However usually you should not be using store.getState() and store.subscribe() in real apps. You should almost exclusively use connect() unless you have a very specific reason why you access low-level APIs.

我将大致像这样重写您的代码:

I would rewrite your code roughly like this:

// ProjectSummary is a presentational component
// that takes projects as a prop and doesn't care
// where it comes from.
const ProjectsSummary = ({ projects }) => {
  return (
    <div className="home-projects col-md-10">
      <h3>Projects</h3>
      <ul>
        {projects.map(p => <li key={p.id}>{p.contract.client}</li>)}
      </ul>
    </div>
  )
}

// Home by itself is also a presentational component
// that takes projects as a prop. However we will
// wrap it in a container component below using connect().
// Note that I got rid of inheritance: it's an anti-pattern
// in React. Never inherit components; instead, use regular
// composition and pass data as props when necessary.
const Home = ({ projects }) => (
  <div className="home-page container-fluid">
    <BasePage />
    <HomeLeftBar />
    <HomePageHeader />
    <ProjectsSummary projects={projects} />
  </div>
)

// How to calculate props for <Home />
// based on the current state of the store?
const mapStateToProps = (state) => ({
  projects: state.projects
})

// Generate a container component
// that renders <Home /> with props from store.
export default connect(
  mapStateToProps
)(Home)

这篇关于使用&lt; Provider&gt;通过上下文传递商店在基于connect()的方案中不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆