Reputation: 46479
I am having trouble figuring out how to pass JSX to my redux state i.e. for modal component that is used globally and has its redux state where one parameter is content
such content can be updated to include JSX code.
At the moment I am getting it to render correct content however it doesn't seem that functions are called correctly and I am also getting following error:
invariant.js:38 Uncaught Error: Objects are not valid as a React child (found: object with keys {dispatchConfig, _targetInst, isDefaultPrevented, isPropagationStopped, _dispatchListeners, _dispatchInstances, nativeEvent, type, target, currentTarget, eventPhase, bubbles, cancelable, timeStamp, defaultPrevented, isTrusted, view, detail, screenX, screenY, clientX, clientY, ctrlKey, shiftKey, altKey, metaKey, getModifierState, button, buttons, relatedTarget, pageX, pageY}). If you meant to render a collection of children, use an array instead or wrap the object using createFragment(object) from the React add-ons. Check the render method of
styled.div
.
With a lot of following errors:
warning.js:36 Warning: This synthetic event is reused for performance reasons. If you're seeing this, you're accessing the property
nativeEvent
on a released/nullified synthetic event. This is set to null. If you must keep the original synthetic event around, use event.persist(). See https://fbme(replaced this as so doesn't allow links to fb)/react-event-pooling for more information.
Example implementation:
Function called from a page to show modal and add contents to it
onToggleModal = () => {
this.props.modalToggle(
(<TopUp account={getSession().accounts[0] || {}} />)
);
}
Where this.props.modalToggle
is a redux action like this:
export const modalToggle = (content = '') => ({
type: MODAL_TOGGLE,
payload: content
});
I then try to render such content inside my Modal container:
return (
<div>{this.props.content}</div>
)
I imported React
into my reducer, in hopes to resolve jsx issues, but had no luck. It also seems like components are passed to reducer as some sort of weird objects.
Upvotes: 5
Views: 2872
Reputation: 1
Hey it's been a while now but for the record I stumbled upon the same use case you are explaining in the reply to the accepted answer.
You can achieve this by adding a property of JsxElement | ReactElement | HTMLElement type in your modalSlice state:
export interface modalState {
active: boolean;
component?: ReactElement;
}
reducers: {
updateModalComponent: (state, value: PayloadAction<ReactElement>) => {
state.component = value.payload;
},
}
Then your modal component file could look something like this:
import { ReactElement } from 'react';
import './modal.scss';
interface Props {
active: boolean,
children: ReactElement | JsxElement | HTMLElement,
}
export const Modal = (props: Props) => {
return (
<div id="modal-container">
{
props.active &&
<div id="overlay">
<div id="modal-content-container">
{props.children}
</div>
</div>
}
</div>
)
}
Finally use it anywhere!
const element = <OtherComponent />;
dispatch(updateModalComponent(element));
Cheers!
Upvotes: 0
Reputation: 90766
Redux state can only contain plain objects and data types, so a JSX object would probably cause issues. Also it's most likely not a good idea to have a JSX object (which is basically a view) as part of your state.
Instead, you should pass around whatever data is required to render the final view. I think this would work:
onToggleModal = () => {
this.props.modalToggle(getSession().accounts[0] || {});
}
export const modalToggle = (account = {}) => ({
type: MODAL_TOGGLE,
account: account
});
return (
<div><TopUp account={account} /></div>
)
Upvotes: 2