Enable linking to routes implicitly, without specifying linking configs, in React Navigation - reactjs

I'm using React Navigation 6.
I want to define a screen with two tabs like so:
<RootTabs.Navigator
initialRouteName='Manage'
>
<RootTabs.Screen name='Manage' component={Placeholder} />
<RootTabs.Screen name='Sell' component={Sell} />
</RootTabs.Navigator>
If I explicitly define a linking config like the following:
const globalLinking: LinkingOptions<any> = {
prefixes: ['https://foo.bar', 'foo://'],
config: {
screens: {
Root: {
path: '',
screens: {
Manage: 'Manage',
Sell: 'Sell',
},
},
},
},
};
Then I can navigate to my "Manage" tab by going to localhost:8080/Manage. If I don't include this above configuration in my Root navigator, I can not.
Is there some way to tell React Navigation to go about enabling deeplinking to these routes without explicitly defining them; instead trusting RNav to implicitly construct these links from the names given to the screens?
TIA

Related

How to create a dynamic layout in react with fully configurable JSON data

I am writing a react application. A core requirement is that the application be completely dynamic and configurable, including choosing layouts, sections and fields, validation etc.
I have two UI. One is the config UI where the user can select the layout, sections, fields like what type of html component etc. Once this is saved, I get data as JSON where I need to draw the UI. This is my second UI. My concern is how do I structure the components to render the UI with the JSON data. The fields & sections will be same but the layout will be different based on what is been selected in the config UI. Below is the rough JSON schema.
{
title: "Test title",
layout: [
{
name: "layout-a"
},
sectionA: {
name: "breadcrumbs"
field: [
{
name: "test",
value: "test",
type: "text"
}
]
},
sectionB: {
name: "actions"
field: [
{
name: "Create",
value: "Create",
type: "button"
}
]
}
]
}
I was thinking of having a layout component which renders all the children from the JSON. Component looks like below
const Layout = ({ children }) => {
return (
<div>
<div className="container">
<div className="content">{children}</div>
</div>
</div>
);
};
and top level component where we read the config json and based on the layout render the component
<Layout>
{viewToShow === "layoutA" && <LayoutA data={config.sections} />}
{viewToShow === "layoutB" && <LayoutB data={config.sections} />}
</Layout>
My question is how do I construct the LayoutA, B or C component so that these sections and fields are rendered differently on the UI?
I think your question leaves a lot of unspecified points for us to offer you a proper solution. My advice is to investigate better what the project real needs are and its main goals, then lay out each piece (component) thoroughly checking what should be "configurable" and to which extent, before coming up with any implementation.
Taking your example "as is", my first thought is to wrap your App component into a Context provider, similar to what we'd do to manage themes.
export const layouts = {
layoutA: {
background: '#fff',
sectionWidth: '100%',
},
layoutB: {
background: '#000',
sectionWidth: '50%',
},
};
export const LayoutContext = React.createContext({
layout: layouts.layoutA, // default layout
toggleLayout: () => {},
})
You could then further populate the layouts object with metadata from a database. Supposing changes do not originate from the UI (think Webflow or Wix Editor), you could use a CMS to update the metadata and propagate the changes.
An example usage would be:
function LayoutTogglerButton() {
return (
<LayoutContext.Consumer>
{({ layout, toggleLayout }) => (
<button
onClick={toggleLayout}
style={{ backgroundColor: layout.background }}>
Toggle Layout
</button>
)}
</LayoutContext.Consumer>
)
}
Again, there are a lot of unspecified points on your request for us to be more specific. The request for "an application to be completely dynamic and configurable, including choosing layouts, sections and fields, validation etc" could mean many things.
Examples of more specific questions: How to create dynamic forms in React with functional components? How to create drag and drop dashboard widgets with React? How to live update/customise themes with styled-components?
Perhaps you could be more specific? Cheers
I am researching a possibility to do something similar. An off the bat approach would look somewhat like this: https://codesandbox.io/s/still-sun-cecudh?file=/src/App.js
Then of course, where this the layout object will be generated and where the parsing will take place will dependent on your use case. I am going with context for layout object generation and a dedicated component for object tree traversal.

Component definition - Missing display name error

I'm trying to build a custom panel option editor in web app called Grafana, but am running into an error I suspect is no more than a React syntax issue.
195:15 error Component definition is missing display name react/display-name
export const optionsBuilder = (builder: PanelOptionsEditorBuilder<SVGOptions>) => {
return builder
.addBooleanSwitch({
category: ['SVG Document'],
path: 'svgAutoComplete',
name: 'Enable SVG AutoComplete',
description: 'Enable editor autocompletion, optional as it can be buggy on large documents',
})
.addCustomEditor({
category: ['SVG Document'],
path: 'svgSource',
name: 'SVG Document',
description: `Editor for SVG Document, while small tweaks can be made here, we recommend using a dedicated
Graphical SVG Editor and simply pasting the resulting XML here`,
id: 'svgSource',
defaultValue: props_defaults.svgNode,
editor: (props) => {
const grafanaTheme = config.theme.name;
return (
<MonacoEditor
language="xml"
theme={grafanaTheme === 'Grafana Light' ? 'vs-light' : 'vs-dark'}
value={props.value}
onChange={props.onChange}
/>
);
},
})
};
To use a custom panel option editor, use the addCustomEditor on the OptionsUIBuilder object in your module.ts file. Configure the editor to use by setting the editor property to the SimpleEditor component.
The tutorial in the Grafana Docs explains more about what I'm doing, but I believe the issue is just with the arrow function I use at line 195.
Is there a different way I should be retrieving my editor property?

How to create a route link for scrolling to an in-page element?

Let's say I have a page with an element like this:
...
<div id="dummy">
</div>
...
I can create a link that scrolls to #dummy like this http://website.com/page#dummy.
My question is, how could I make a link in the form of http://website.com/page/dummy and behaves exactly the same as the above link (links to page and just scrolls to #dummy)?
Also I want the url of the page to change to http://website.com/page/dummy if the user scrolled to #dummy element.
Is there something readily available in Next.js or React that allows me to do this?
One way of doing this is with redirects. Just create next.config.js and add following configuration
module.exports = {
async redirects() {
return [
{
source: "/page/:slug",
destination: "/page#:slug",
permanent: true,
},
];
},
};

React-Localization setLanguage() does not update the page

What am I trying to achieve
Currently, I am trying to implement localization within our current React-Native project.
To do this, I choose the following package: React-Localization
Our project makes usage of React-Native in combination with TypeScript.
What is the problem
I have written a function to set the language from "en" to "nl".
Then I have two pages:
Home (contains the function to change the language & has a Text element)
Settings (has a Text element)
Only the text on the Home page gets updated. The text element on the Settings page is not getting translated. Also my header and bottom navigation are not translated.
What code am I using
To switch the language
switchLanguage() {
if (translationStrings.getLanguage().toLowerCase() == 'nl') {
translationStrings.setLanguage('en');
} else {
translationStrings.setLanguage('nl');
}
this.setState({});
}
Translations
export const translationStrings = new LocalizedStrings({
en: {
tempTest: "English test one",
tempTest2: "English test two"
},
nl: {
tempTest: "Dutch test een",
tempTest2: "Dutch test twee"
}
});
Examples of the elements that I am trying to translate.
// This is on the home page so it works.
<Text>
{translationStrings.tempTest}
</Text>
// This is on the settings page and it does not work.
<Text>
{translationStrings.tempTest2}
</Text>
Also, the header and bottom navigation is not updating/getting translated.
Could someone give me some insight into what I am exactly doing wrong?
It feels like I should give the application a sign that everything has been translated and that it should reload or something.
So for the other pages, I have used React Redux to translate the content.
I managed to get my bottom navigator translated by doing the following changes for the navigation options.
Old ->
Settings: {
screen: Settings,
navigationOptions: {
tabBarLabel: i18next.t('Settings')
},
},
New -->
Settings: {
screen: Settings,
navigationOptions: ({ navigation, navigationOptions }) => ({
tabBarLabel: i18next.t('Settings')
}),
},

How to make custom theme using Shoutem's StyleProvider that properly uses underlying INCLUDE

I really love the shoutem theme library, but I'm finding it difficult to hook into the recursive INCLUDE that makes the underlying code work beautifully (See code+documentation here: https://github.com/shoutem/theme/blob/develop/src/Theme.js). For instance, if we have:
render() {
return (
<StyleProvider style={theme}>
<View />
</StyleProvider>
);
}
const theme = _.merge(getTheme(), {
'shoutem.ui.Text': {
color: 'green',
},
});
This simple text color change will work, but only for shoutem Text components. However, Heading, Title, Subtitle, etc. all of which pull from Text attributes in the shoutem library because of INCLUDE. The use of a simple _.merge(...) only overwrites the component itself, but not anything that it might subsequently affects. It sounds like I need to overwrite attributes higher up in the tree (e.g., Text), and then regenerate the theme so it affects all "children" that it's included in (e.g., Heading and Title). Using the publicly exposed API, is this possible to do somehow at the moment? Or are there any forks or utilities you're aware of that accomplish this with your library.
There is a text property in the root of the default shoutem ui theme that is included into all text elements (https://github.com/shoutem/ui/blob/develop/theme.js#L292). You should be able to accomplish your use case by simply overriding values from that property:
const theme = _.merge(getTheme(), {
text: {
color: 'green',
},
});
In case you want to create a more complex theme, you can use INCLUDE in your code as well. INCLUDE works by merging all values from top level theme properties it targets. You can use it to include properties from the base theme, and you can also include your own custom properties:
import { INCLUDE } from '#shoutem/theme';
const theme = _.merge(getTheme(), {
// Define a top level property to use in includes
largeText: {
fontSize: 20,
},
'shoutem.ui.Text': {
// Include a text property from the base theme
// and a largeText property defined above
[INCLUDE]: ['text', 'largeText'],
// Override the text color after all includes
// have been resolved
color: 'green',
},
});
Sometimes specific components define styles after INCLUDEs have been resolved, those styles have a higher priority, and will always override the style from INCLUDEs. To change those styles, you can use a createSharedStyle helper:
import { createSharedStyle } from '#shoutem/theme';
const textComponents = [
'shoutem.ui.Heading',
'shoutem.ui.Title',
'shoutem.ui.Subtitle',
'shoutem.ui.Text',
'shoutem.ui.Caption',
];
const theme = _.merge(getTheme(), {
...createSharedStyle(textComponents, {
color: 'green',
},
});
Finally, some more basic customizations can be done through theme variables, you can pass custom variables when calling getTheme(https://github.com/shoutem/ui/blob/develop/theme.js#L55-L144).

Resources