A recent 'react-admin' update moved 'title' into the 'appbar' - how do I push it back into the content? - appbar

With release v2.3.0 the title was moved into the appbar. I want it in the content, and to maintain the app name in the appbar. How can I do that?

I solved this by creating a custom logo element that I set in each action:
// In appTitle.js
import React from 'react';
const AppTitle = () => (
<a href='http://localhost:3000/#/'>
<p>YOUR_APP'S_TITLE</p>
</a>
);
export default AppTitle;
Then import this to your components list and use it as follows:
// In your posts.js for example
import AppTitle from '../appTitle';
export const PostList = (props) => (
<List {...props} title={<AppTitle/>}>
...
Doing this for all of your actions (Edit, Show, Create) for each entity.
Of course you can create your own custom appbar but I chose this option as simpler.
If you want your title for the current post (in example) to be shown, you can display it within the list as a <TextField source="title"/>.

Related

Testing-library unable to find rc-menu

I'm trying to implement integration tests on our React frontend which uses Ant design. Whenever we create a table, we add an action column in which we have a Menu and Menu Items to perform certain actions.
However, I seem unable to find the correct button in the menu item when using react-testing-library. The menu Ant design uses is rc-menu and I believe it renders outside of the rendered component.
Reading the testing-library documentation, I've tried using baseElement and queryByRole to get the correct DOM element, but it doesn't find anything.
Here's an example of what I'm trying to do. It's all async since the table has to wait on certain data before it gets filled in, just an FYI.
Tried it on codesandbox
const row = await screen.findByRole('row', {
name: /test/i
})
const menu = await within(row).findByRole('menu')
fireEvent.mouseDown(menu)
expect(queryByRole('button', { name: /delete/i })).toBeDisabled()
the menu being opened with the delete action as menu item
I had a same issue testing antd + rc-menu component. Looks like the issue is related to delayed popup rendering. Here is an example how I solved it:
jest.useFakeTimers();
const { queryByTestId, getByText } = renderMyComponent();
const nav = await waitFor(() => getByText("My Menu item text"));
act(() => {
fireEvent.mouseEnter(nav);
jest.runAllTimers(); // ! <- this was a trick !
});
jest.useRealTimers();
expect(queryByTestId("submenu-item-test-id")).toBeTruthy();

How to use a native SwiftUI View in NativeScript 7

In my NativeScript (Angular) App i use a RadListView to create a list and each element has many different informations to display. It looks like that
Because of many hints at Stackoverflow and other sources i reduced the amount of nested layouts (StackLayout, GridLayout, ...) as much as possible to make the RadListView faster. On Android is the performance by using the list much better as on iOS. With an iPad Pro (2020) the rendering of the list at scrolling is not smooth. If the user change the orientation of the device the screen is freezing and have black bars at the side or bottom for a moment. The time of the freezing depends on the amount of elements to display in each row. The same row layout in a ListView is much faster but not the same as native (SwiftUI) and with missing features like swipe and pull to refresh.
Sorry for the lyric but i think a little background explains why i try the next step.
To improve the user experience i make a tiny native test app with SwiftUI and nearly the same row layout. The feeling is much better, fast first loading, smooth scrolling and no delay by orientation changes. My next idea is to create a native component in SwiftUI to show/render each row of the RadListView if possible
<RadListView [items]="items">
<ListViewLinearLayout tkListViewLayout></ListViewLinearLayout>
<ng-template tkListItemTemplate let-item="item" let-i="index" let-odd="odd">
<MyNativeSwiftUIComponentElement data="item.rowData"></MyNativeSwiftUIComponentElement>
</ng-template>
</RadListView>
or use the List from SwiftUI to show/render the whole list
<ActionBar title="Objects"></ActionBar>
<MyNativeSwiftUIListComponent data="items"></MyNativeSwiftUIListComponent>
Looking for docs and examples was difficult. I found this very short advise Adding Objective-C/Swift code and the linked tutorial there for Objective-C (Adding Objective-C Code to a NativeScript App) and some questions on Stackoverflow but there all about classes and not SwiftUI (with struct and views). One question was about SwiftUI: Is it possible to display a View written with SwiftUI with NativeScript the answer was unfortunately not helpful for me (btw. thank you #Manoj for your great support for NativeScript at Stackoverflow!).
How can i use a SwiftUI View as native component in my {N}app?
Have anyone a hint, a link to a tutorial or a link to a public repository for a app/plugin? Every tiny tip is welcome.
You might be able to use Nativescript's placeholder component (more info on that here
So you would have the Placeholder tag on your template, and use the creatingView event to add the native UIs
<Placeholder creatingView="creatingView"/>
import { CreateViewEventData } from "#nativescript/core";
export function creatingView(args: CreateViewEventData) {
let nativeView = new UILabel(); // where this would be your native UI
nativeView.text = "Native";
args.view = nativeView;
}
After a while i give up with my attempts to use directly SwiftUI in the project ({N}+Angular) and instead i try the <Placeholder> component which #William-Juan suggested. But it looks like, that the <Placeholder> not official supported in the Angular flavor - see github issue #283
To move on, i looked at the samples for NativeScript plugins and build a working solution. If anybody interested the full sample source code are in this repository: https://github.com/teha-at/sample-nativescript-native-ui-component
First, create a class which extends the #nativescript/core/View class and has an item to get the data which will be to display.
// object-list-item.d.ts
// [...]
export class ObjectListItem extends View {
item: ObjectModel;
}
export const itemProperty: Property<ObjectListItem, string>;
Than create a abstract base class which also extends the #nativescript/core/View class and this creates the base for Android and iOS
// object-list-item.common.ts
// [...]
export const itemProperty = new Property<ObjectListItemBase, string>({
name: 'item',
defaultValue: null,
affectsLayout: isIOS,
});
export abstract class ObjectListItemBase extends View {
item: PortalObjectModel;
}
// defines 'item' property on the ObjectListItemBase class
itemProperty.register(ObjectListItemBase);
ObjectListItemBase.prototype.recycleNativeView = 'auto';
Because i was only looking for a component for iOS the object-list-item.android.ts are very simple:
// object-list-item.android.ts
import { ObjectListItemBase } from './object-list-item.common';
export class ObjectListItem extends ObjectListItemBase {}
For iOS there are much more lines, for the complete file content look at the github repo please.
/// object-list-item.ios.ts
// [...]
export class ObjectListItem extends ObjectListItemBase {
// added for TypeScript intellisense.
nativeView: UIView;
// [...]
/**
* Creates new native button.
*/
public createNativeView(): Object {
const mainUiStackView = UIStackView.new();
// [...]
}
/**
* Initializes properties/listeners of the native view.
*/
initNativeView(): void {
// Attach the owner to nativeView.
// When nativeView is tapped we get the owning JS object through this field.
(<any>this.nativeView).owner = this;
super.initNativeView();
}
/**
* Clean up references to the native view and resets nativeView to its original state.
* If you have changed nativeView in some other way except through setNative callbacks
* you have a chance here to revert it back to its original state
* so that it could be reused later.
*/
disposeNativeView(): void {
// Remove reference from native listener to this instance.
(<any>this.nativeView).owner = null;
// If you want to recycle nativeView and have modified the nativeView
// without using Property or CssProperty (e.g. outside our property system - 'setNative' callbacks)
// you have to reset it to its initial state here.
super.disposeNativeView();
}
[itemProperty.setNative](item: ObjectModel) {
this.item = item;
// [...]
}
}
Add an Angular directive
// object-list-item.directives.ts
#Directive({
selector: 'ObjectListItem',
})
export class ObjectListItemDirective {
}
export const ObjectListItemDirectives = [ObjectListItemDirective];
At least register the component in an Angular module.
// object-list-item.module.ts
// [...]
#NgModule({
imports: [],
declarations: [
ObjectListItemDirectives,
],
schemas: [NO_ERRORS_SCHEMA],
exports: [
ObjectListItemDirectives,
],
entryComponents: [],
})
export class ObjectListItemModule {
}
registerElement('ObjectListItem', () => ObjectListItem);
After all this steps call the new component in the template
<!-- [...] -->
<RadListView #myListView [items]="items$ | async">
<ng-template tkListItemTemplate let-item="item">
<StackLayout margin="0" padding="0" class="-separator m-y-5" height="90">
<android>
<!-- [...] -->
</android>
<ios>
<ObjectListItem [item]="item"></ObjectListItem>
</ios>
</StackLayout>
</ng-template>
</RadListView>
<!-- [...] -->
All this work is well spent. The UI is much faster and it feels more like a native app. At the mean time i build a prototype as a native iOS App in Swift and SwiftUI, of course this pure native app are a little bit more smoother, but at the moment i work with my {N}-App and the native component. Hope this sample will be useful for someone.

How add react-relay component to the storybook?

I am trying create a storybook for my react-realy app, but i don't know how to set mockup data for that component. For simple a component it is ok, because i can use dummy UI component vs Container approach, but i can't use this for nested relay components, for example there is a UserList component, which i want add to storybook, i can split relay fragment part to container and UI part to the component, but what if UserList children are too relay component? I can't split their when they are a part of the composition of UserList?
Is there some solution for add relay components to the storybook?
I created a NPM package called use-relay-mock-environment, which is based on relay-test-utils which allows you to make Storybook stories out of your Relay components.
It allows nesting of Relay components, so you can actually make stories for full pages made out of Relay components. Here's an example:
// MyComponent.stories.(js | jsx | ts | tsx)
import React from 'react';
import { RelayEnvironmentProvider } from 'react-relay';
import createRelayMockEnvironmentHook from 'use-relay-mock-environment';
import MyComponent from './MyComponentQuery';
const useRelayMockEnvironment = createRelayMockEnvironmentHook({
// ...Add global options here (optional)
});
export default {
title: 'MyComponent',
component: MyComponent,
};
export const Default = () => {
const environment = useRelayMockEnvironment({
// ...Add story specific options here (optional)
});
return (
<RelayEnvironmentProvider environment={environment}>
<MyComponent />
</RelayEnvironmentProvider>
);
};
export const Loading = () => {
const environment = useRelayMockEnvironment({
forceLoading: true
});
return (
<RelayEnvironmentProvider environment={environment}>
<MyComponent />
</RelayEnvironmentProvider>
);
};
You can also add <RelayEnvironmentProvider /> as a decorator, but I recommend not doing that if you want to create multiple stories for different states/mock data. In the above example I show 2 stories, the Default one, and a Loading one.
Not only that, it requires minimal coding, where you don't need to add the #relay-test-operation directive to your query, and the mocked data is automatically generated for you using faker.js, allowing you to focus on what matters, which is building great UI.
Feel free to review the source code here if you want to implement something similar: https://github.com/richardguerre/use-relay-mock-environment.
Note: it's still in its early days, so some things might change, but would love some feedback!
I also created relay-butler, which is a CLI that takes in GraphQL fragments and outputs Relay components, including a auto-generated query component that wraps the fragment component, and Storybook stories (the Default and Loading ones by default) that wrap that query component. And literally within minutes, I can create beautiful Relay components that are "documented" within Storybook.
Would also love some feedback for it!

React Native Stateless component saying undefined

I'm trying to create a component using React Native like so:
export class IndicatorOverlay extends Component {
render() {
return (
<View>
<Text>text</Text>
</View>
);
}
};
The above works, but when I try to make it stateless like so...
export default ({ text = 'text' }) => {
return (
<View>
<Text>{text}</Text>
</View>
);
};
I get the following error:
Element type is invalid: expected a string (for built-in components)
or a class/function (for composite components) but got: undefined. You
likely forgot to export your component from the file it's defined in.
I'm sure I'm missing something basic, but I just can't see it. I use a similar stateless component in a React web app and it's fine.
Using react 16.0.0-alpha.6 and react-native 0.43.2, and am seeing this error in the iPhone simulator.
Hope someone can help :)
This is likely because the first example is a named export, while the second one is a default one therefore the way need to import them is different.
Assuming you import your module like this:
import { IndicatorOverlay } from 'IndicatorOverlay';
you have two options. Either:
1) change the way you import your module (since the stateless component is a default export now):
import IndicatorOverlay from 'IndicatorOverlay';
2) keep the import intact, but refactor your stateless component to something like this:
export const IndicatorOverlay = ({text = 'text'}) => {
return (
<View>
<Text>{text}</Text>
</View>
);
};
You can make it more DRY btw:
export const IndicatorOverlay = ({ text = 'text' }) => (
<View>
<Text>{text}</Text>
</View>
);
You can read more about imports and exports on MDN:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export

onsenui with Cordova - start application on specific screen

I'm running a React.js/Cordova/OnsenUI application that is intended to be used both in the browser and on mobile devices. I'd like the user to be able to scan a QR code, then jump to a screen in my application.
This is what the application looks like right now:
import React from 'react';
import {
Navigator
} from 'react-onsenui';
import MainPage from './MainPage';
import Vendor from './Vendor';
const renderPage = (route, navigator) => (
<route.component key={route.key} navigator={navigator} />
);
const App = () => (
<Navigator
renderPage={renderPage}
initialRoute={{component: MainPage, key: 'MAIN_PAGE'}}
/>
);
export default App;
When I start up, depending on the URL, I might want to start with a Vendor component or a MainPage component.
I figured that the easiest thing to do would be to dynamically create the initialRoute object based on the QR code that was scanned. Given that I might be on an iOS device, how do I know what the URL was that was scanned? Is there a different way that I should be jumping to a specific screen when I start the app?

Resources