如何向 React 的 props 添加数据

How to add data to React's props

我正在尝试使用 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;

我不明白的是如何将 frontload() 中的 page 传递给 frontloadConnect() 中的 props,这就是我想的应该做的。

我的 getPage() returns 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.

我是 react-frontload 的作者。

What I don't get is how to pass page in frontload() to props in frontloadConnect()

你不能,至少不能直接。你的 frontload 函数应该 return a Promise<void> 并且不应该以任何方式修改(或变异)props - 它不会 'pass on' 支持底层组件。

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

为了用代码进行说明,这是您使用 redux 的示例(省略了 reducer 等以保持简短)

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 不需要关心异步 state/props 管理,可以将其留给您已经在使用的状态管理解决方案。