如何向React的道具添加数据

时间:2018-08-18 17:55:43

标签: javascript reactjs serverside-rendering

我正在尝试使用react-frontload实现SSR。该库的作者已在https://hackernoon.com/react-frontload-3ff68988cca上写了一个教程。到目前为止,其他所有内容都说得通了,但是在这个示例的开头,我无法弄清楚getProfileAsync()中发生了什么(取自上面的教程):

import { frontloadConnect } from 'react-frontload'

// assuming here that getProfileAsync returns a Promise that
// resolves when the profile is loaded into props.boundProfile
const frontload = (props) => (
  getProfileAsync(props.username)
)

// all available options, set to the default values
const options = {
  noServerRender: false,
  onMount: true,
  onUpdate: true
}

// just decorate the same underlying component from earlier
const ProfileView =
  frontloadConnect(frontload, options)((props) => (
    props.profile
      ? <div>{props.profile.fullName}'s profile</div>
      : <div>loading..</div>
  ))

这是我尝试实现的方法:

const frontload = props => (
  getPage('/home').then(page => props.page = page)
);

const ContentRoute =
  frontloadConnect(frontload)(props => (
    props.page
      ? <div>Content goes here</div>
      : <div>Loading...</div>
  ));

export default ContentRoute;

我没有得到的是如何将page中的frontload()传递到props中的frontloadConnect(),这是我应该做的。

我的getPage()通过axios返回一个承诺:

const getPage = route => axios
  .get('...query...')
  .then(res => res.data.data.pages[0]);

我想它可以正常工作,因为getPage('/home').then(page => console.log(page))记录了我要寻找的对象。

非常感谢!

EDIT1:我得到的错误是:Uncaught (in promise) TypeError: Cannot add property page, object is not extensible

1 个答案:

答案 0 :(得分:1)

我是react-frontload的作者。

  

我不明白的是如何将frontload()中的页面传递给frontloadConnect()中的道具

您不能,至少不能直接。您的frontload函数应该返回一个Promise<void>并且不应以任何方式修改(或变异)props-它不会将prop传递给基础组件。

相反,它应该执行异步请求,然后使用您选择的状态管理解决方案更新状态。这可以是redux,也可以像具有react组件状态的父组件一样简单。当然,状态管理代码需要包装在一个函数中,该函数作为道具传递到更上层的链中,然后可以从frontload函数访问。

为了用代码说明,这是您使用redux的示例(为简化起见,省略了减速器等)

const mapState = (state) => ({
  page: state.page
})

const mapDispatch = (dispatch) => ({
  updatePage: () => (
    getPage('/home')
      .then(page => dispatch({ type: 'UPDATE_PAGE', page }))
  )
})

const frontload = props => (
  // state update left to redux connected function 
  // which is added to props further up the chain
  // i.e. props are not directly modified in the frontload function
  props.updatePage() 
);

const ContentRoute =
  connect(mapState, mapDispatch)(
  frontloadConnect(frontload)(props => (
    props.page // page is connected from redux state
      ? <div>Content goes here</div>
      : <div>Loading...</div>
  )));

export default ContentRoute;

为什么?因为这种方式react-frontload不需要关心异步状态/道具管理,而可以将其留给您已经在使用的状态管理解决方案。