You ask:
"Is it a good idea to store components in state?
Is it good practice to store whole React Components in the component state or redux
state?
[...] but in some cases, it is simpler to just store the component in the state.
Is this a bad practice?"
No, it's not a good idea.
No, it's not good practice.
No, that is never simpler.
Yes, it's a bad practice, decidedly.
React is based upon one simple yet powerful core concept: a function receives some values (the properties) and returns the elements that are to be rendered as the immediate result of the current set of values. (All other concepts are only auxiliary: state, side-effects, lifecylce, synthetic events, refs, memoization, tachyon emitters and numberwang)
Storing elements for later use directly breaks this core concept. You risk having stale elements that do not correspond to the current set of properties. (And even if your elements do not have any properties as input you will not gain anything useful by putting them in the state, read on.)
And what is even the intended use of creating react elements and putting them in the state? What perceived problem do want to solve?
I can make out two things that you probably try to achieve by doing so: 1. having a means to conditionally render an element; and 2. somehow optimizing the number of times a new react element is created.
For both these aims the modus operandi of putting react elements into the state is ill fitted.
For both these aims React provides straightforward solutions:
Conditionally rendered elements are achieved thus:
const [showPrompt, setShowPrompt] = useState(false);
// ...
<div>
{ showPrompt && <ConfirmationPrompt /> }
</div>
or by using a prop
const MyComponent = ({showPrompt}) => {
// ...
<div>
{ showPrompt && <ConfirmationPrompt /> }
</div>
This is simple, it is clear, it is correct. Nothing breaks. No future maintainer is compelled to curse you or poison your vanilla chai latte.
If you have reason to think your render function is quite heavy and you want to reduce the number of times it is run, you can use the useMemo hook (to memoize calculation results within you render function) or you can wrap your whole component in React.memo() so it is only re-rendered when the props change. (You should employ both mechanisms only when you can actually measure any difference.)
const primeNumbers = useMemo(() => calculatePrimeNumbers(limit), [limit]);
const MyComponent = React.memo((props) => {
/* render using props */
});