-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
react2angular fails with: renderWithSharedContext is not a function #11
Comments
I ran into this same error. I think the trick is to add the component somewhere in your application. Without it, it never creates an instance of the shared context. |
Yes, adding the component and fixing the issue. Here is the complete code with some typescript alignments: import React, {
ComponentProps,
ComponentType,
Fragment,
FunctionComponent,
useEffect,
useLayoutEffect,
useRef,
useState
} from 'react'
import { createPortal } from 'react-dom'
import { v4 as uuid } from 'uuid'
interface IComponent {
key: string
node: HTMLElement
component: ComponentType<any>
props: any
}
interface IComponentInstance<T> {
update: (props: T) => void
remove: () => void
}
const createSharedContext = (Root: ComponentType<any> = Fragment, isAsync = true) => {
// Make method accessible by both SharedContext and withSharedContext
let renderWithSharedContext: {
(component: IComponent): IComponentInstance<ComponentProps<typeof component.component>>
} = () => ({
update: () => {},
remove: () => {}
})
const SharedContext: FunctionComponent<ComponentProps<typeof Root>> = rootProps => {
// List of components and their props to be rendered with react portal in their designated nodes
const [components, setComponents] = useState<Array<IComponent | undefined>>([])
useEffect(() => {
renderWithSharedContext = (component: IComponent) => {
// Add component to list
setComponents(prevState => {
prevState.push(component)
return [...prevState]
})
// Return callbacks to update and remove component from list
return {
update: props => {
setComponents(prevState => {
const prevComponent = prevState.find(c => c?.key === component.key)
if (!prevComponent) {
return prevState
}
prevComponent.props = props
return [...prevState]
})
},
remove: () => {
setComponents(prevState => {
const index = prevState.findIndex(c => c?.key === component.key)
if (index === -1) {
return prevState
}
prevState[index] = undefined
return [...prevState]
})
}
}
}
}, [])
// Return list of react portals wrapped in one or multiple providers
return (
<Root {...rootProps}>
{components.map(component => {
if (!component) {
return null
}
const { key, node, component: C, props } = component
return createPortal(<C key={key} {...props} />, node)
})}
</Root>
)
}
const useSharedContext: (component: ComponentType<any>) => FunctionComponent<any> = component => {
// Create as local variable instead of returning inline to fix TSLint
const UseSharedContext: FunctionComponent<ComponentProps<typeof component>> = props => {
// Create unique key for this instance
const key = useRef(uuid())
// Hold reference to rendered hidden DOM node
const ref = useRef<HTMLDivElement>(null)
// Instance is SharedContext
const instance = useRef<IComponentInstance<ComponentProps<typeof component>>>()
;(isAsync ? useEffect : useLayoutEffect)(() => {
if (instance.current) {
// Pass prop updates to instance in SharedContext
instance.current.update(props)
}
}, [props])
;(isAsync ? useEffect : useLayoutEffect)(() => {
if (ref.current && ref.current.parentElement) {
// Create instance in SharedContext
instance.current = renderWithSharedContext({
key: key.current,
node: ref.current.parentElement,
component,
props
})
// Return callback to unmount component in SharedContext when this component is unmounted
return instance.current.remove
}
return
}, [])
// Hidden <div> component only used to get reference in dom
return <div ref={ref} style={{ display: 'none' }} />
}
return UseSharedContext
}
return {
component: SharedContext,
use: useSharedContext
}
}
export default createSharedContext |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Due some reason, the react2angular initially fails with renderWithSharedContext.
Here is the snippet that initializes the react2angular-shared-context:
Here is the trace:
The text was updated successfully, but these errors were encountered: