【问题标题】:React When does rendering happenReact 渲染何时发生
【发布时间】:2021-02-20 21:43:10
【问题描述】:

我的项目使用dvajs(基于redux和redux-saga),下面的代码是点击按钮后发送请求,通过connect改变状态,然后调用ant design组件message.error一个@ 987654323@(类似alert)提醒

import type { Dispatch } from 'umi';
import ProForm, { ProFormText } from '@ant-design/pro-form';
import { message } from 'antd';

const tip = (type: string, content: string) => {
  if (type === 'error') message.error(content, 5);
  else message.success(content, 5);
};

const RegisterFC: React.FC<RegisterProps> = (props) => {
  const { registerResponseInfo = {}, submitting, dispatch } = props;
  const { status } = registerResponseInfo;

  const handleSubmit = (values: RegisterParamsType) => {
    dispatch({
      type: 'register/register',
      payload: { ...values },
   });
};      

  return (
    <div>
      <ProForm
         onFinish={(values) => {
            handleSubmit(values as RegisterParamsType);
            return Promise.resolve();
    }}
       >
       <ProFormText/>
       ...
      {
        status === '1' && !submitting && (
          tip('error',
            intl.formatMessage({
              id: 'pages.register.status1.message',
              defaultMessage: 'error'
            })
          )
        )
      }
    <<ProForm>/>
    </div>
  )
}

const p = ({ register, loading }: { register: RegisterResponseInfo, loading: Loading; }) => {
  console.log(loading);
  return {
    registerResponseInfo: register,
    submitting: loading.effects['register/register'],
  };
};

export default connect(p)(RegisterFC);

当我点击按钮时,控制台提示:

警告:渲染方法应该是 props 和 state 的纯函数; 不允许从渲染触发嵌套组件更新。如果 必要时,在 componentDidUpdate 中触发嵌套更新。

当状态改变时组件不会重新渲染吗?提示函数会改变状态吗?

【问题讨论】:

  • 这里的代码不完整且令人困惑。什么是p,它叫什么名字? handleSubmit如何访问dispatch? (它在组件内部吗?)我收到另一个错误,这是由于您在div 中打印来自tip()void 结果。 tip 更新全局 message 对象,但它不返回任何内容。
  • 对不起,由于代码太多,我只截取了部分代码。我对代码做了进一步的改进。 p 在最后一行被connect 调用,handleSubmit 应该在组件内部。您的意思是在tip() 中添加return
  • tip 可以是 void,但您应该在组件的 return JSX 之外调用它。在组件主体的某处,if (status === '1' &amp;&amp; !submitting) { tip(...); }
  • 好的,但是如果我将tip(..) 替换为FunctionComponent,则不会出现警告。为什么?代码如下{ status === '0' &amp;&amp; !submitting &amp;&amp; ( &lt;RegisterMessage /&gt;}
  • &lt;RegisterMessage /&gt; 是您要呈现给 DOM 的 JSX 元素。调用tip() 的结果是什么都没有。它是void。所以你不能渲染它。

标签: reactjs redux render redux-saga dvajs


【解决方案1】:

解决方案:在return之外调用tip

tip 只是您正在调用的function。您应该在代码的 return JSX 部分之外调用它。我认为在依赖statussubmittinguseEffect 挂钩中调用它是最有意义的。每次statussubmitting 更改时,效果都会运行。如果status1submittingfalsy,那么我们调用tip

const RegisterFC: React.FC<RegisterProps> = (props) => {
    const { registerResponseInfo = {}, submitting, dispatch } = props;
    const { status } = registerResponseInfo;

    const handleSubmit = (values: RegisterParamsType) => {
        dispatch({
            type: 'register/register',
            payload: { ...values },
        });
    };

    React.useEffect(() => {
        if (status === '1' && !submitting) {
            tip('error',
                intl.formatMessage({
                    id: 'pages.register.status1.message',
                    defaultMessage: 'error'
                })
            );
        }
    }, [status, submitting]);

    return (
        <div>...</div>
    )
}

说明

渲染方法应该是 props 和 state 的纯函数

组件的渲染部分(类组件中的render() 或函数组件中的return)是您根据props 和@ 的当前值为组件创建JSX(React HTML)标记的地方987654340@。它不应该有任何副作用。它创建并返回 JSX,仅此而已。

调用tip 是一个副作用,因为它会修改全局antd messsage 对象。这意味着它不应该在代码的render 部分。副作用通常在 useEffect 钩子内部处理。

您正在尝试有条件地渲染tip,就像您有条件地渲染组件一样。问题是tip 不是组件。函数组件是返回 JSX 元素的函数。 tip 是一个 void 函数,它什么都不返回,所以你不能渲染它。

【讨论】:

    猜你喜欢
    • 2019-12-10
    • 2021-12-06
    • 2020-10-20
    • 2019-08-02
    • 1970-01-01
    • 2021-06-05
    相关资源
    最近更新 更多