无法使用Redux连接Next.js App,无法使用err进行渲染

时间:2018-04-12 18:23:36

标签: reactjs redux next.js

我把它放在C9上,因为它有很多依赖项,它可能更容易阅读那里的代码,而不是在这里展示它。

https://ide.c9.io/noman2000/showfer-media

请参阅MainWrapper.jsxLibraryView.jsxLibrary.jsxconnect.js

应用程序本身在这里运行:

https://showfer-media-noman2000.c9users.io/

nextjs团队在这里有一个示例应用程序:

https://github.com/zeit/next.js/tree/master/examples/with-redux

但我需要转换我的应用程序,这有点不同。我这样做时给出的错误是:

Warning: Functions are not valid as a React child. This may happen if you return a Component instead of <Component /> from render. Or maybe you meant to call this function rather than return it.
    in Unknown (created by Container)
    in AppContainer (created by Container)
    in Container (created by App)
    in App

重要的一点。我有一个显示此组件Library.jsx的路线。

// @flow
import React from "react"
import PropTypes from "prop-types"
import routes from "./../../../server/routes/routes"
import commonApi from "./../../../app/common/common"
import LibraryItem from "./../../../app/components/library/LibraryItem"
import detectEnvironment from "./../../../app/common/detect-environment"

const { categoryContent } = commonApi
const { isMobileFromWidth } = detectEnvironment
const { Router } = routes

class Library extends React.Component<Props> {

  componentWillMount() {
    this.props.actions.setActiveCategory(null, "", -1)
  }

  authLibraryItems = ["favorites", "history", "queue"]

  advtLabel = (label: string) => {
    const { library } = this.props.state.toJS()

    const sourceUrl = library.serviceTypes[label].source_url
    const slashOrder = sourceUrl.substr(8).search("/") + 1

    return sourceUrl.substr(8).slice(slashOrder)
  }

  render() {
    const { auth, library, layout } = this.props.state.toJS()
    const titles = library.serviceTypes.heading
    const categoryClasses = isMobileFromWidth()
      ? categoryContent(layout.orientation)
      : "category-content"

    return (
      <React.StrictMode>

          <section>
            <div className={categoryClasses}>
              <div className="library-title-container">
                <div className="library-title">{titles && titles.title}</div>
                <div className="library-subtitle">{titles && titles.subtitle}</div>
              </div>

              <div className="library-menu scrolling-wrapper">
                <h1>I can display!</h1>
              </div>
            </div>
          </section>
      </React.StrictMode>
    )
  }
}

export default Library

该组件包含在网页LibraryView.jsx

import connectWrapper from "./../app/redux/utils/connect"
import root from "./../app/redux/rootReducer"
import Library from './../app/components/main/Library'
import MainWrapper from './../app/components/main/MainWrapper'

const { rootActions } = root

export default MainWrapper(connectWrapper(rootActions, Library))

MainWrapper.jsx看起来像这样:

// @flow
/* eslint-disable */
import root from "window-or-global"
import React from "react"
import { fromJS } from "immutable"
import { connect, Provider } from "react-redux"
import "babel-polyfill"
import storeConfiguration from "../../redux/configureStore"
import rootReducer from "../../redux/rootReducer"
import commonApi from "./../../common/common"

const { getOrCreateStore  } = storeConfiguration


export default (...args) => (Component) => {
  // First argument is initStore, the rest are redux connect arguments and get passed
  const [initStore, ...connectArgs] = args
  console.log(Component)
  const ComponentWithRedux = (props = {}) => {
    const { store, initialProps, initialState } = props

    // Connect page to redux with connect arguments
    const ConnectedComponent = connect.apply(null, connectArgs)(Component)

    // Wrap with redux Provider with store
    // Create connected page with initialProps
    return React.createElement(
      Provider,
      { store: store && store.dispatch ? store : getOrCreateStore(initStore, initialState) },
      React.createElement(ConnectedComponent, initialProps)
    )
  }

  ComponentWithRedux.getInitialProps = async (props = {}) => {
    const isServer = checkServer()
    const store = getOrCreateStore(initStore)

    // Run page getInitialProps with store and isServer
    const initialProps = Component.getInitialProps
      ? await Component.getInitialProps({ ...props, isServer, store })
      : {}

    return {
      store,
      initialState: store.getState(),
      initialProps
    }
  }

  return ComponentWithRedux
}

最后,connect.js文件。

// @flow
import { connect } from "react-redux"
import { bindActionCreators } from "redux"
import immutable from "immutable"

const connectWrapper = (actions: {}, view: any) => {
  const mapStateToProps = state => ({ state })

  const mapDispatchToProps = (dispatch: Function) => ({
    actions: bindActionCreators(actions, dispatch),
  })

  return connect(mapStateToProps, mapDispatchToProps)(view)
}
export default connectWrapper

我想要做的是能够将任何组件传递到MainWrapper(connectWrapper(rootActions, <ANY REACT COMPONENT>))并将其包装在redux存储中,但这不起作用。

更新

这部分由MainWrapper()(connectWrapper(rootActions, <Any React Component>))解决,但它非常不稳定。

1 个答案:

答案 0 :(得分:2)

如果我理解正确,你正在尝试为next.js构建自己的redux-wrapper HOC。我建议使用next-redux-wrapper库,它可以找到here和一个很好的例子。

您只需使用next-redux-wrapper提供的withRedux HOC包装所有页面组件,并且所有子组件都可以包含在react-redux提供的connect函数中,正如它们在docs中所述:

  

使用withRedux仅包装顶级页面!所有其他组件应该继续使用React Redux的常规连接功能。