My project use dvajs
(Based on redux and redux-saga), The code below is to send a request after clicking the button, change the status through connect, and then call the ant design component message.error
an message.success
(Similar to alert) to remind
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);
When I click the button, the console prompts:
Warning: Render methods should be a pure function of props and state; triggering nested component updates from render is not allowed. If necessary, trigger nested updates in componentDidUpdate.
Doesn't the component re-render when the state changes? Does the tip function change the state?
tip
Outside of return
tip
is just a function
that you are calling. You should call it outside of the return
JSX section of your code. I think it makes the most sense to call it inside of a useEffect
hook with dependencies on status
and submitting
. The effect runs each time that status
or submitting
changes. If status
is 1
and submitting
is falsy, then we call 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>
)
}
Render methods should be a pure function of props and state
The render section of a component (render()
in class component or return
in a function component) is where you create the JSX (React HTML) markup for your component based on the current values of props
and state
. It should not have any side effects. It creates and returns JSX and that's it.
Calling tip
is a side effect since it modifies the global antd
messsage
object. That means it shouldn't be in the render
section of the code. Side effects are generally handled inside of useEffect
hooks.
You are trying to conditionally render tip
like you would conditionally render a component. The problem is that tip
is not a component. A function component is a function which returns a JSX Element. tip
is a void
function that returns nothing, so you cannot render it.