React-Redux how to export component function to window object - reactjs

I am building a React-redux library that displays a widget chat. The library should provide an interface allowing the client to configure and understand the state of the library and, render widgets into their document.
I use Webpack for the build process.
I use Twilio-Chat library for the chat features.
My index file looks like this:
Index.js
import MyChatWidget from 'components/MyChatWidget';
export default {
widgets: {
MyChatWidget: {
render: (args) => {
ReactDOM.render(
<MyChatWidget />
);
},
logout: () => {
// this function should call a the logout in the MyChatWidget
// React Component
}
}
}
MyChatWidget
import Chat from 'twilio-chat';
class MyChatWidget extends Component {
logout() {
Chat.shutdown()
}
}
export default connect()(MyChatWidget);
The logout is exposed to the client and it should call a function inside the MyChatWidget component.
How can I achieve this behaviour?
Am I including the Twilio Chat in the wrong place(MyChatWidget Component)?
I read this article for the building with webpack (https://codeburst.io/building-react-widget-libraries-using-webpack-e0a140c16ce4)

Disclaimer: I'm not a huge fan of putting anything on the window object, especially because if you use server rendering the window isn't available. But passing an instance of your class to the window object would make it accessible anywhere JS has access to the window object.
constructor() { super(); if ( window ) { window.mychatwidget = this; } }

You can declare the logout method static and access that method as MyChatWidget.logout() in your index.js

Related

platform.pause.subscribe at Ionic-React

I am using Ionic Framework with React. I want to run a code when platform.pause as mentioned in ionic-react-platform.
But the codes in react documents are unbelievably for angular instead of react!
I want exactly code below, but for react not for angular. Can any one help me with it please?
import { Platform } from '#ionic/angular';
#Component({...})
export class MyPage {
constructor(public platform: Platform) {
}
init(){
this.platform.pause.subscribe(async () => {
alert('Pause event detected');
});
}
}
You can try by setting a listener inside your App component (or wherever you need it)
import { App } from '#capacitor/app';
App.addListener('appStateChange', ({ isActive }) => {
// state.isActive contains the active state
console.log('App state changed. Is App in foreground?', isActive);
});

React Developer Tools shows all components as "Anonymous"

I've installed the React Developer Tools extension on Google Chrome to debug a React application written in TypeScript, but once I start debugging the application and open the "Components" window, all components are shown as "Anonymous".
Granted, the application uses mostly function components.
Does anyone know if there is a way to get React Developer Tools to show component names in its component tree?
This happens when you define your components like so:
// Default arrow function export
export default () => {
// ...
}
// Default function export
export default function() {
// ...
}
You can replace with the following to fix the issue:
const CustomComponent = () => {
// ...
}
export default CustomComponent;
// or
export default function YourComponent() {
// ...
}
If you're using an exported anonymous functional component or a memo'ed component; it would be shown as Anonymous
Refer this - https://github.com/facebook/react/issues/17876
Or try solutions mentioned here - React Dev tools show my Component as Unknown

How to use inversify.js in react redux application on the service layer

I would like to use inversify in react-redux application but only in the service layer and not via componenet
I have the service of a setting that need to call to API (Http service)
I would like a kind of provider that will give me the option to call settingsService.get() in the actions.ts file
How do i initialize the objects of all my services
my actions.ts file: I guess to bring container here and use conainter.get... is a bad practice
export const increment = () => (dispatch: any) => {
dispatch({
type: INCREMENT
});
};
My settings Service
#injectable()
export class SettingsService implements Settings {
#inject(TYPES.Test) private testService!: Test;
get() {
// some api call
return this.testService.test();
}
}
My inversify.ts
const container = new Container();
function init() {
container
.bind<Settings>(TYPES.Settings)
.to(SettingsService)
.inSingletonScope();
container
.bind<Test>(TYPES.Test)
.to(TestService)
.inSingletonScope();
}
export { container, init };
My question :
1 - where do I initialize the services? is the definition in iversify.ts is ok? do I need to initialize the container in index.ts on the react app? now I call init() in index.ts
2 - how do I call to settingsService in the actions.ts ( action.ts is not class-based) is a redux action function
3- should easy to test
My stack
React, redux, typescript

Extending AWS Amplify Auth components in typescript

So I'm trying to extend the existing Auth components in AWS Amplify such as SignIn, SignUp, etc. and override the showComponent() function to return a custom form as detailed in this post: https://blog.kylegalbraith.com/2018/11/29/how-to-easily-customize-the-aws-amplify-authentication-ui/
I'm using typescript for my nextjs project and I'm getting the following error: when I try to throw the custom component under the Authenticator component:
[ts]
JSX element type 'CustomSignUp' is not a constructor function for JSX elements.
Type 'CustomSignUp' is missing the following properties from type 'ElementClass': render, context, setState, forceUpdate, and 3 more.
Here's my _app.tsx:
import {SignUp} from 'aws-amplify-react/dist/Auth/SignUp';
class NewApp extends App {
static async getInitialProps({Component, ctx}) {
let pageProps = {};
if (Component.getInitialProps) {
pageProps = await Component.getInitialProps(ctx);
}
return { pageProps }
}
render() {
const {props} = this as any
const {Component, pageProps} = props
return (
<Container>
<Authenticator hide={[SignUp]}>
<CustomSignUp/>
<Component {...pageProps}/>
</Authenticator>
</Container>
)
}
}
export default NewApp;
And the CustomSignUp.tsx is just something stupidly simple for demonstration purposes:
class CustomSignUp extends SignUp {
_validAuthStates;
constructor(props) {
super(props);
this._validAuthStates = ['signUp'];
}
showComponent(theme) {
return(
<div>
Hi!
</div>
)
}
}
export default CustomSignUp;
What's the way to do this correctly?
Per your request above I will provide more detail. As I mentioned in my comment, we found implementing and customizing the AWS Amplify components to be restrictive and difficult. We therefore decided to simply build out our own UI Components as we normally would, manage authentication globally with the Amplify HUB module and a Cognito Auth method helper class. Finally, we pushed Cognito user data down through our components with our own simple HOC.
To start, in a Component mounted when your app first loads, you can import Hub from aws-amplify to add any event listeners relevant to your app in the Component -- perhaps in the constructor -- including listeners to monitor auth state:
Hub.listen("auth", data => {
const { payload } = data;
if (payload.event === "signOut") {
props.navigation.navigate("SigninScreen");
}
}
You can listen/respond to auth changes throughout your app, even if the component in which you established the listeners unmounts.
Next, you can build a simple class with the various methods from the Auth module, again imported from aws-amplify, encapsulating functionality such as Auth.currentAuthenicatedUser, Auth.signUp, etc. With our own UI we simply attached/invoked the Cognito methods at the appropriate places and time.
If you decide to take this route, the last gap to fill is how to pass down the data from Auth's currentAuthenticatedUser method to your components (as Amplify's out of the box HOC would do). You can make your own HOC which fetches user data by Auth.currentAuthenticatedUser(), and pass the received data via props to any Component it wraps - fairly straightforward.
Because we were using graphql/Apollo, in our case we decided to use Apollo Client local resolvers to retrieve/pass Cognito user data. You can read more about Apollo Client local resolvers here here if you're interested.

Exposing React child component to JavaScript on webpage

I'm pretty new to rxjs, and trying to understand what's needed here to expose the Chat object in the Bot Framework, as I need to call some methods in it I'll add. I essentially need access to the created Chat component from the webpage, which right now has a BotChat.App. There's also a BotChat.Chat, but that doesn't seem to be the instance I need access to.
The following is used from the Bot Framework by calling BotChat.App({params});
That in turn creates a Chat component (eventually in App.tsx below). I need to basically expose the Chat instance that is used, as I want to modify it.
BotChat.ts (Complete)
export { App, AppProps } from './App';
export { Chat, ChatProps } from './Chat';
export * from 'botframework-directlinejs';
export { queryParams } from './Attachment';
export { SpeechOptions } from './SpeechOptions'
export { Speech } from './SpeechModule'
import { FormatOptions } from './Types';
// below are shims for compatibility with old browsers (IE 10 being the main culprit)
import 'core-js/modules/es6.string.starts-with';
import 'core-js/modules/es6.array.find';
import 'core-js/modules/es6.array.find-index';
And here in App.tsx note the Chat component used below. That is what I need to expose up through the webpage. A bit confused as to if it's exporting a "Chat" type as opposed to getting access to the instance of Chat being used in App.tsx. Hope this makes some sense :)
App.tsx (Complete)
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { Chat, ChatProps } from './Chat';
import * as konsole from './Konsole';
export type AppProps = ChatProps;
export const App = (props: AppProps, container: HTMLElement) => {
konsole.log("BotChat.App props", props);
ReactDOM.render(React.createElement(AppContainer, props), container);
}
const AppContainer = (props: AppProps) =>
<div className="wc-app">
<Chat { ...props } /> //<--------------This is what I want to get
//access to on the webpage, which currently
//only uses BotChat.App() to initialize the
//web chat control. Not sure how to expose
//this _instance_ to App.tsx and then expose
//that instance to the webpage.
</div>;
Web Chat has a Redux store and a RxJS stream that you can expose to interact with the <Chat> component. In React, you can, but people usually don't expose any functions out of it. Short reason: the contract of a React component is props, not functions.
For RxJS stream that you can access the chat history, you can look at the backchannel sample. But it's a read-only stream.
For other interactivities, look at Store.ts to see what actions it is using. Then, expose the Redux store at Chat.ts (easy hack: thru window variable, better: make a callback props at <Chat>).
If you need more interactivities that is not in the existing Redux actions, feel free to add some more. For example, this pull request should give you a sense of injecting chat history.

Resources