【发布时间】:2017-11-29 14:00:11
【问题描述】:
在哪些反应生命周期方法 (https://facebook.github.io/react/docs/react-component.html) 中允许/禁止/推荐/不推荐调度 redux 操作?为什么?
假设我的无状态组件使用从服务器加载的数据,是否可以在 render() 期间调度操作以安排 ajax 调用?
【问题讨论】:
标签: reactjs redux react-redux
在哪些反应生命周期方法 (https://facebook.github.io/react/docs/react-component.html) 中允许/禁止/推荐/不推荐调度 redux 操作?为什么?
假设我的无状态组件使用从服务器加载的数据,是否可以在 render() 期间调度操作以安排 ajax 调用?
【问题讨论】:
标签: reactjs redux react-redux
答案是固执己见,但通常不受欢迎:生命周期方法被调用以响应组件树上的状态更改,但调度操作将可能启动另一个状态更改。这是 redux 试图避免的事件处理程序级联更新情况:您应该根据操作进行状态更改,而不是其他任何事情,否则您将拥有这些反应循环。状态变化是一次性发生的。
实际上,为了方便起见,这条规则经常被放宽。所以没有真正的正确答案!就像软件开发中的大多数事情一样,它是微妙的。
关于在渲染中不这样做(或任何不纯的东西)的其他答案是正确的:您想要的事件可能是“当这个组件被挂载时”与“每当它的渲染被调用时”这更好由constructor 处理或componentWillMount。此外,componentDidMount/componentWillUpdate/componentDidUpdate 更好地服务于您想要在渲染中完成的任何事情。
【讨论】:
didComponentMount() 应该关心render() 使用什么(在从服务器加载内容的情况下)。我的意思是,这会导致逻辑重复,每当我更改render() 时,我需要更改didComponentMount(),需要确保两者一致。这是错误的来源。我看不到通过将 ajax 调用放入 didComponentMount() 获得什么,也许有可能将 ajax 请求处理到服务器?是的。一点都不简单。
如果您正在谈论通过操作触发 ajax 调用,您应该使用componentDidMount,这是 facebook 明确推荐的,上面写着If you need to load data from a remote endpoint, this is a good place to instantiate the network request.
这是因为渲染组件可能比从服务器获取响应花费更多的时间,然后 ajax 回调触发了未安装组件的渲染。这是一个边缘案例,自从我使用 React 开发以来,我只发生过一次,但是为了安全起见,您应该在 componentDidMount 中触发 ajax 调用。
如果您的 redux 操作只是对商店进行更改,那么您可以随时调度它。
【讨论】:
ReactDOM.render() ?所以你说ReactDOM.render() 在ajax 调用返回之后完成?但不是ReactDOM.render() 同步/阻塞吗?这样任何ajax调用的返回ReactDOM.render()实际上不能在ReactDOM.render()返回之前运行?我很迷惑。你能解释一下吗?
setState 既不会填充初始状态,也不会导致重新渲染,这就是不鼓励使用 componentWillMount 中的 AJAX 的原因。但我不确定 100%。
您不应在 render() 方法中调度操作。以下是来自 react 文档的引用:
render()函数应该是纯函数,也就是说它不修改组件状态,每次调用都返回相同的结果,不直接与浏览器交互。如果您需要与浏览器交互,请在componentDidMount()或其他生命周期方法中执行您的工作。保持render()pure 使组件更易于思考。
当您需要从服务器获取数据时,最好在组件挂载后进行,即在componentDidMount() 方法中。反应文档指出:
componentDidMount()在组件安装后立即调用。需要 DOM 节点的初始化应该放在这里。如果您需要从远程端点加载数据,这是一个实例化网络请求的好地方。在此方法中设置状态将触发重新渲染。
如果来自服务器的数据依赖于组件的某些props 或state,您还需要实现componentWillReceiveProps() 或componentWillUpdate() 函数来获取新数据。
【讨论】: