Render pilet under a tab - micro-frontend

I want to render a pilet under a tab. I have managed to render the pilet name as a tab but content can't be renderd. I am using Fluent UI Pivots.
https://developer.microsoft.com/en-us/fluentui#/controls/web/pivot
The idea is when you click a a Tab/Pivot name the micro front end should be loaded.

The easiest way I see is to use a conventional extension slot for doing that. A more obvious way (for pilet developers) would be to have a custom API like registerTab for registering tab components.
Following the easy way you could the following for your Pivot:
export const MyTabComponent = () => {
return (
<ExtensionSlot name="tabs" render={children => (
<Pivot>
{children.map((child, i) =>
<PivotItem headerText="First Tab" key={i}>
{child}
</PivotItem>
)}
</Pivot>
)} />
);
};
Using this in your app shell all you'd need to do in a pilet is register an extension for tabs.
export function setup(api) {
api.registerExtension("tabs", () => <div>Sample content!</div>);
}

Related

How do I avoid visual bug when navigating from one screen to another? - React Native Expo

I'm creating a sign in screen and a create account screen on my application. I have buttons that go back and forth to each other. Both screens work fine individually. When I do this, there can often be a visual error like so:
My App.js Code:
const App = () => {
return (
<NavigationContainer theme={theme}>
<Stack.Navigator screenOptions={{ headerShown: false}} initialRouteName="CreateAccountScreen">
<Stack.Screen name ="CreateAccountScreen" component={CreateAccountScreen} />
<Stack.Screen name ="SignInScreen" component={ SignInScreen } />
</Stack.Navigator>
</NavigationContainer>
);
}
Code from each Screens button that goes back and forth:
onSignUpButtonPressed = () => {
navigation.navigate("SignInScreen")
}
onCreateAccountButtonPressed = () => {
navigation.navigate("CreateAccountScreen")
}
Displays seem to overlay themselves in a bad way
I've tried a bunch of things and this has happened on several screens...
Your initialRouteName is set up as we can see but on your Stack.Screen you also give it the Component attribute.
I did a test based on how my navigation looks and I did not get the visual bug you showed so I think if you removed the component attribute and maybe just put the component tag inside your Stack.Screen as shown below it might work. Just imagine my Home is your CreateAccountScreen.
<Stack.Navigator
initialRouteName='Home'
>
<Stack.Screen
name="Home"
options={{
headerShown: false,
}}
>
{props => <Home {...props} username='Bella' />}
</Stack.Screen>
You also dont have the code in your question to define Stack like this:
const Stack = createStackNavigator();

Load WooCommerce data on demand and show it in a DataGrid by Syncfusion

I need to load all the products in my nodeJS application with WooCommerce Rest Api. I use the WooCommerce REST API - JavaScript Library and the Syncfusion Grid Component. Because I can't load all data at once, I wanted to use the Load data on demand like this, but I can't find any documentation or examples on this.
I have something like this:
import React from 'react';
import { useEffect, useState } from "react";
import { GridComponent, ColumnsDirective, ColumnDirective, Resize, Sort, ContextMenu, Filter, Page, ExcelExport, PdfExport, Edit, Inject } from '#syncfusion/ej2-react-grids';
import WooCommerceRestApi from "#woocommerce/woocommerce-rest-api";
var WooCommerce = new WooCommerceAPI({
url: 'http://example.com',
consumerKey: 'ck_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
consumerSecret: 'cs_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
wpAPI: true,
version: 'wc/v1'
});
const WooCommerceProducts = () => {
const [products, setProducts] = useState([]);
useEffect(() => {
fetchOrders();
}, []);
let fetchOrders = () => {
WooCommerce
.get("products", {
per_page: 100,
page: 1
})
.then((response) => {
if (response.status === 200) {
setProducts(response.data);
}
})
.catch((error) => { });
};
return (
<div className='m-2 md:m-10 p-2 md:p-10 bg-white rounded-3xl'>
<Header category="Page" title="WooCommerce Orders" />
<GridComponent
id='gridcomp'
dataSource={orders}
allowPaging
allowSorting>
<ColumnsDirective>
<ColumnDirective field='id' />
<ColumnDirective field='name' />
<ColumnDirective field='slug' />
<ColumnDirective field='status' />
...
</ColumnsDirective>
<Inject services={[Resize, Sort, ContextMenu, Filter, Page, ExcelExport, PdfExport]} />
</GridComponent>
</div>
)
}
export default WooCommerceProducts
Please help and thx
If you are using any custom services, I suggest you use the custom-binding feature to bind the data to the grid. I would like to share the behavior of custom-binding in EJ2 Grid. 
For every grid action (such as Filter, Page, etc.,), I have triggered the dataStateChange event, and, in the event arguments, I have sent the corresponding action details (like skip, take, filter field, value, sort direction, etc.,) Based on that, you can perform the action in your service, return the data as a result, and count objects. 
Note: ‘dataStateChange’ event is not triggered at the Grid initial render. If you are using a remote service, you need to call your remote service by manually with a pagination query (need to set the skip value as 0 and take a value based on your pageSize of pageSettings in Grid. If you are not defined pageSize in pageSettings, you need to send the default value 12 ) in load event of Grid. Please return the result like as "{result: […], count: …}" format to Grid. 
‘dataSourceChanged’ event is triggered when performing CRUD actions in Grid. You can perform the CRUD action in your service using action details from this event, and, you need to call the endEdit method to indicate the completion of the save operation. 
Custom-binding: https://ej2.syncfusion.com/react/documentation/grid/data-binding/data-binding/#custom-binding
Demo: https://ej2.syncfusion.com/react/demos/#/material/grid/custom-binding
sample: https://stackblitz.com/edit/react-v64sms-wx3hsy?file=index.js

passing function between separate components in react not between child and parent

I have a small question regarding passing functions between components that are not in parent/child relationship.
My structure inside App.
function App() {
return (
<div className="App">
<Header/>
<Pfl />
<Sdc/>
<Checkscan/>
</div>
);
}
Those 3 components have an on click function attached to a button i want the button from the pfl component to trigger all 3 on click functions.
When i click on the button in the pfl component i want to trigger the function running in the pfl component and the functions that are inside the Sdc,Checkscan component.
Whats the best way to do it and pass the functions from the other components so when i click the button inside the pfl component it will trigger all the methods from the other 2 components(Sdc,Checkscan)?
Or if I make a container that looks like this
export default function Apicontainer() {
return (
<React.Fragment>
<Pfl />
<Sdc />
<Checkscan />
<Button variant="contained">Start</Button>
</React.Fragment>
)
}
and in app.js i only have the Apicontainer.
How do i transfer all the functions to work in that button click Component
I just wrote some quick and dirty example code to show how you can share things between components via a parent component:
export default function Apicontainer() {
const [sharedState, setSharedState] = useState({sdc: null, checkScan: null})
function pflFunction() {
console.log('pflFunction')
// do your stuff here. I would update state with some reasonable data, and then pass
// the relevant data to the component that needs it. This is just an example.
setSharedState({sdc: 'sdcData', checkScan: 'checkScanData'})
}
return (
<React.Fragment>
<Pfl onClick={pflFunction} />
<Sdc data={sharedState.sdc}/>
<Checkscan data={sharedState.checkScan} />
<Button variant="contained">Start</Button>
</React.Fragment>
)
}
// Example of how to trigger a function inside a component (separate file):
export default function Sdc({data}){
const sdcFunction = useCallback(() => {
// implement the function you want to call here. useCallback makes sure to keep
// a stable reference to the function, so that you can rely on it in a useEffect
}, [])
useEffect(() => {
if(data){
// do something. This effect will run whenever the data or sdcFunction changes.
sdcFunction()
}
}, [data, sdcFunction])
return (
<div>your Sdc view code here</div>
)
}
For the record: If fplFunction is anything else than an onClick handler, you should make sure the function has a stable reference, using useCallback (as in the last component)

how to change website theme and save this theme so it doesn't change on reload?

I found a lot of website, that it allows me to change the website theme , without being logged in.
and when i refresh the page the theme doesn't reset. I was wondering how can i do that , or can someone put me on the right pass.
do i focus on the back-end , or it's only on front-end (client-side).
does it website to browser related. or it's something else ? i really looked a lot tried to save the the client choose into his db, but now when i see website that i can change it, without even being logged in so it's not related to db.
or is it session related ?
You can keep the theme information in localStorage in your users' browsers. When the app starts you can check if there is any theme information in the localStorage and use that, and when you update the theme you can set it in localStorage.
Example
class App extends React.Component {
state = {
theme: localStorage.getItem("theme") || "red"
};
toggleTheme = () => {
this.setState(
({ theme }) => ({
theme: theme === "red" ? "green" : "red"
}),
() => {
localStorage.setItem("theme", this.state.theme);
}
);
};
render() {
return (
<div style={{ backgroundColor: this.state.theme }}>
<div>Welcome to my website</div>
<button onClick={this.toggleTheme}> Toggle theme </button>
</div>
);
}
}
You can use something like this in Reactjs (obviously you would need to implement the MyTheme and SelectInput components yourself):
class MyReactComp extends React.Component {
setTheme(theme) {
localStorage.setItem('theme', selectedTheme);
}
render() {
<MyThemeLayout theme={localStorage.getItem('theme')} />
<MySelectInput onChange={theme => this.setTheme(theme)} />
}
}
Otherwise, you could send the theme choice to the backend, store it in MongoDB or something and then set an ID cookie so that the theme can be retrieved when the user next visits the site.

Leave screen callback React Navigation Tab Navigator

I have a React Navigation Tab Component like this:
const RootNavigator=TabNavigator({
Home:{
screen: Home,
navigationOptions:{
tabBarIcon: ({focused}) => (
<Icon
name={focused? 'ios-home':'ios-home-outline'}
style={{color: '#464646'}}
size={16}
/>
)
}
},
Notifications:{
screen: Notifications,
navigationOptions:{
tabBarIcon: ({focused}) => (
<TabNotifications focused={focused} />
)
}
}, {});
Is there a way to make a callback when leaving a screen?
In this case, I would like to perform a function when I leave the Notifications tab. Such as mark the notifications as seen and remove the badge indicator.
As of now, I am pulling the Notification icon from another component in order to show the number badge.
Thanks in advance.
One option is to use onNavigationStateChange to check the current change of the navigation and do the action you need to clear notifications etc.
onNavigationStateChange(prevState, newState, action)
Function that gets called every time navigation state managed by the
navigator changes. It receives the previous state, the new state of
the navigation and the action that issued state change. By default it
prints state changes to the console.
Another option is to use addListener. This way you can subscribe to willFocus/didFocus or willBlur/didBlur events and do the action you need.
addListener - Subscribe to updates to navigation lifecycle
React Navigation emits events to screen components that subscribe to
them:
willBlur - the screen will be unfocused
willFocus - the screen will focus
didFocus - the screen focused (if there was a transition, the transition completed)
didBlur - the screen unfocused (if there was a transition, the transition completed)
Example from the docs
const didBlurSubscription = this.props.navigation.addListener(
'didBlur',
payload => {
console.debug('didBlur', payload);
}
);
// Remove the listener when you are done
didBlurSubscription.remove();
// Payload
{
action: { type: 'Navigation/COMPLETE_TRANSITION', key: 'StackRouterRoot' },
context: 'id-1518521010538-2:Navigation/COMPLETE_TRANSITION_Root',
lastState: undefined,
state: undefined,
type: 'didBlur',
};
For those who want a third option, you could use the NavigationEvents component as suggested by the docs to listen to navigations hooks and to whatever you intended to do.
Edit: This is documentation for React Navigation 2.x, which is no
longer actively maintained. For up-to-date documentation, see the
latest version (6.x).
import React from 'react';
import { View } from 'react-native';
import { NavigationEvents } from 'react-navigation';
const MyScreen = () => (
<View>
<NavigationEvents
onWillFocus={payload => console.log('will focus',payload)}
onDidFocus={payload => console.log('did focus',payload)}
onWillBlur={payload => console.log('will blur',payload)}
onDidBlur={payload => console.log('did blur',payload)}
/>
{/*
Your view code
*/}
</View>
);
export default MyScreen;

Resources