How to disable Navbar component in dynamic routes in next.js.? - url

I Know one way of doing this is by using the next router, but only in case when the route is static like /dashboard'.But how to do it when the URL is dynamic like '/story/[slug]'.
Layout.js
const Layout=({children })=>{
if(router.pathname != '/dashboard')
return(
<>
{children()}
</>
)
else{
return(
<>
<Navbar/>
{children()}
</>
)
}
}
export default Layout;
This works but instead of /dashboard i need to implement this in all the dynamic routes under /story like /story/[slug] .
Thanks in advance

I'd use a simple javascript method: includes.
const App = ({ Component, pageProps }) => {
const router = useRouter();
const withoutLayoutArray = [
'story'
];
const isWithoutLayout = withoutLayoutArray.includes(router.pathname);
return isWithoutLayout ? (
<Provider store={store}>
<Component {...pageProps} />
</Provider>
) : (
<Provider store={store}>
<NavBar>
<Component {...pageProps} />
</NavBar>
</Provider>
);
})

Related

How to use draft-js-plugins in react-hook-form

I am using react-hook-form and draft.js as wysiwiyg.
My code where I am using draft-js-plugins:
import React, {useRef} from "react";
import { Controller } from "./src";
import Editor from "#draft-js-plugins/editor";
import createToolbarPlugin from "#draft-js-plugins/static-toolbar";
import "draft-js/dist/Draft.css";
import "#draft-js-plugins/static-toolbar/lib/plugin.css";
const staticToolbarPlugin = createToolbarPlugin();
const { Toolbar } = staticToolbarPlugin;
const plugins = [staticToolbarPlugin];
function RichText({ control }) {
const editor = useRef(null);
return (
<div
style={{
border: "1px solid #ccc",
minHeight: 30,
padding: 10
}}
>
<Toolbar />
<Controller
ref={editor}
name="DraftJS"
control={control}
plugins={plugins}
render={({ value, onChange }) => {
return <Editor editorState={value} onChange={onChange} />;
}}
/>
</div>
);
}
export default RichText;
All is ok, I see plugins. But when I want select word and click to plugin (I, B, U) button show me error
props.getEditorState is not a function
I don't understand how to solve it? I found some examples https://www.draft-js-plugins.com/plugin/static-toolbar .but didn't help
live example on codesandbox
I think you have to place the <Toolbar /> component as a sibling to your <Editor /> component and also pass the ref to it.
<Controller
name="DraftJS"
control={control}
render={({ value, onChange, ref }) => {
return (
<>
<Toolbar />
<Editor
ref={ref}
editorState={value}
onChange={onChange}
plugins={plugins}
/>
</>
);
}}
/>

How to hide certain sections using gatsby-theme-i18n-react-i18next?

I have a project that uses Gatsby and for localization, I have used gatsby-plugin-react-i18next plugin. I have to hide few sections in the menu for some languages. How to hide it?
Just use a conditional rendering.
const YourComponent = (props) => {
const { language } = useI18next();
return (
<div>
{language === 'en' ? <OneComponent /> : <OhterComponent />}
</div>
);
};
You can extend the condition to a function that returns a component:
const YourComponent = (props) => {
const { language } = useI18next();
const handleComponent = () =>{
if(language === 'en') return <OneComponent />
else(language === 'es') return <OhterComponent />
}
return (
<div>
{handleComponent()}
</div>
);
};
As you can see in the docs, the exposed language variable holds the current language.

Should a component adapter wrap just the component or should it also wrap <Field>

Best concept for wrapping react-final-form components
Background
I'm using react-native and will probably start using react-final-form as soon as I have wrapped my head around it. I will build a component library based on react-native-paper.
All examples I've seen on wrapping 3:rd party components for use as react-final-form fields (i.e. <Field>), does not wrap the actual field component. Instead the wrapped component is injected via the component property of the Field component.
If I'm doing all the work wrapping the components, why not go all the way? Since I haven't found any examples of the "complete wrapping", I'm kind of worried that it's not a good idea.
Both solutions seems to work fine, btw. The code below is psuedo:ish.
Only wrapping the component
export default function App() {
const CheckboxAdapter = ({input: {onChange, value}, meta}) => (
<Checkbox
status={value}
onPress={() => {
onChange(value === 'checked' ? 'unchecked' : 'checked');
}}
errorText={meta.touched ? meta.error : ''}
/>
);
return (
<Form
..
render={({handleSubmit}) => {
return (
..
<Field
name="myFieldname"
component={CheckboxAdapter}
/>
)
}
/>
)
}
Wrapping the component inside of the <Field> component
export default function App() {
const MyCheckbox = ({name}) => (
<Field
name={name}
component={({input: {onChange, value}, meta, children, ...rest}) => (
<Checkbox
status={value}
onPress={() => {
onChange(value === 'checked' ? 'unchecked' : 'checked');
}}
errorText={meta.touched ? meta.error : ''}
/>
)};
/>
);
return (
<Form
..
render={({handleSubmit}) => {
return (
..
<MyCheckbox
name="myFieldname"
/>
)
}
/>
)
}
Not much interest in this question. I ended up wrapping the <Field>as well. This gives much more readable form code.
import React from 'react';
import TextInput from '../components/TextInput';
import {Field} from 'react-final-form';
const TextInputAdapter = ({input, meta, ...rest}) => {
const onChangeText = value => {
input.onChange(value);
};
return (
<TextInput
{...input}
{...rest}
onChangeText={onChangeText}
errorText={meta.touched ? meta.error : ''}
/>
);
};
const TextInputField = ({...rest}) => {
return <Field component={TextInputAdapter} {...rest} />;
};
export default TextInputField;

Want to pass data to other component - ListView

I have added and imported the sample data. I want to list out data from this file in a list view and I'm passing the data to the Row Component for RenderRow. But getting error saying
Row(...): A valid React element (or null) must be returned. You may have returned undefined, an array or some other invalid object.
import React, { Component } from 'react';
import { AppRegistry, View, ListView, Text, StyleSheet } from 'react-native';
import Row from './app/Row';
import data from './app/Data';
export default class ListViewDemo extends Component {
constructor(props) {
super(props);
const rowHasChanged = (r1, r2) => r1 !== r2
const ds = new ListView.DataSource({rowHasChanged});
this.state = {
dataSource: ds.cloneWithRows(data),
};
render() {
return (
<ListView
dataSource={this.state.dataSource}
renderRow={(data) => <Row {...data} />} // Getting error here
/>
);
}
}
AppRegistry.registerComponent('DemoApp',() => ListViewDemo)
These my sample Data.js You can check the data here.
export default data = [
{...}, {...}
];
Row.js:
const Row = (props) => {
<View Style={styles.container}>
<Image source={{ uri: props.picture.large}} />
<Text >
{`${props.name.first} ${props.name.last}`}
</Text>
</View>
}
What would be the problem?
ES6 only returns when there is no explicit blocks:
const cb = (param) => param * 2;
You should explicitly return:
const Row = (props) => {
return (
<View Style={styles.container}>
<Image source={{ uri: props.picture.large}} />
<Text >
{`${props.name.first} ${props.name.last}`}
</Text>
</View>
);
}
Check this answer for further explanation.
Change this Line to
renderRow={(data) => <Row {...data} />}
To This
renderRow={(data) =><Row {...this.props} />}
This may help you to get props in the row Component

Redux router pushState function not triggering URL change

I have followed the example here to try and create a basic authenticated area
for my app, which is a solution I really like in principle. Here is my index.js:
const store = createStore(reducer);
ReactDOM.render(
<Provider store={store}>
<Router history={hashHistory}>
<Route path="/" component={App}>
<IndexRedirect to="authenticated" />
<Route path="setup" component={SetupJourney} >
<Route path="details" component={Details}/>
<Route path="account" component={AccountType}/>
</Route>
<Route path="authenticated" component={requireAuthentication(secretPage)} />
</Route>
</Router>
</Provider>,
document.getElementById('root')
);
and then here's my AuthenticatedComponent higher-order component to handle redirects:
export function requireAuthentication(Component) {
class AuthenticatedComponent extends React.Component {
componentWillMount() {
this.checkAuth();
}
componentWillReceiveProps(nextProps) {
this.checkAuth();
}
checkAuth() {
if (!this.props.isAuthenticated) {
this.props.dispatch(pushState(null, '/setup/details', ''));
}
}
render() {
return (
<div>
{this.props.isAuthenticated === true
? <Component {...this.props}/>
: null
}
</div>
)
}
}
const mapStateToProps = (state) => ({
isAuthenticated: state.get('user').get('isAuthenticated')
});
return connect(mapStateToProps)(AuthenticatedComponent);
}
I've been playing about with this for ages and I cannot get the component to redirect. In Redux dev tools I can see the ##reduxReactRouter/historyAPI action has fired, but the URL doesn't change. All the relevant props/state etc seem to be in place too...is there something I've missed?
Thanks
For anyone coming across this, I eventually resolved this and there were a few problems. Firstly, pushState is only for use with browserHistory, so I needed to switch from hashHistory.
After this the pushState still did not work. This can apparently happen when middleware is specified in the wrong order. I restructured my index.js to follow the pattern in Redux's real world example, and everything eventually worked.
The key bit is I now have a store.js file that looks like this:
import { createStore, applyMiddleware, combineReducers, compose } from 'redux';
import { routerReducer, routerMiddleware} from 'react-router-redux';
import { browserHistory } from 'react-router';
import reducer, { INITIAL_STATE } from '../reducers/reducer';
const rootReducer = combineReducers({reducer, routing: routerReducer});
const composeEnhancers =
process.env.NODE_ENV !== 'production' &&
typeof window === 'object' &&
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ?
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({
}) : compose;
const enhancer = composeEnhancers(
applyMiddleware(routerMiddleware(browserHistory))
);
const initialState = {'reducer': INITIAL_STATE};
export default function configureStore() {
return createStore(rootReducer, initialState, enhancer);
}

Resources