I am using react-router V6 for navigation and noticed strange behavior in navigation.
When you go to a new page, the following happens: go to the desired page, redirect back and again to the desired page.
This is not the first time I have used this version, but this is the first time I meet this behavior.
did anyone face a similar problem?
My routes.ts
const routes = (isLogged: boolean, dispatch: AppDispatch) => {
if (!localStorage.getItem('auth')) {
<Navigate to="/login" />;
revokeUserInfo(dispatch);
}
const revoke = () => {
if (isLogged && isAuthExpired()) {
revokeUserInfo(dispatch);
}
return false;
};
revoke();
return [
{
path: 'app',
element: isLogged ? <DashboardLayout /> : <Navigate to="/login" />,
children: [
{
path: 'dashboard',
element: <Dashboard />
},
{
path: 'chargers',
element: <Outlet />,
children: [
{
path: '',
element: <Chargers />
},
{
path: ':id',
element: <ChargerInfo />
},
]
},
{
path: 'location/:id',
element: <LocationInfo />
},
{
path: 'activity',
element: <Outlet />,
children: [
{
path: 'sessions',
element: <Sessions />
},
{
path: 'transactions',
element: <Transactions />
},
],
},
{
path: 'business',
element: <Outlet />,
children: [
{
path: '',
element: <Business />
},
{
path: ':id',
element: <BusinessInfo />
},
]
},
{
path: '*',
element: <Navigate to="/404" />
}
]
},
{
path: '/',
element: !isLogged ? <MainLayout /> : <Navigate to="/app/dashboard" />,
children: [
{
path: 'login',
element: <Login />
},
{
path: '/',
element: <Navigate to="login" />
},
{
path: 'resetPassword',
element: <ResetPassword />
},
{
path: '404',
element: <NotFound />
},
]
},
{
path: '*',
element: <Navigate to="/404" />
}
];
};
export default routes;
My App.tsx
const App: FC = () => {
const { isLogged } = useSelector((state: RootStateType) => state.auth);
const dispatch = useDispatch();
const routing = useRoutes(routes(isLogged, dispatch));
return (
<PersistGate
loading={<Spinner />}
persistor={persistor}
>
{/* Permissions Casl Context */}
<AbilityContext.Provider value={ability}>
{/* Material UI theme context Context */}
<StylesProvider
generateClassName={generateClassName}
injectFirst
>
<ThemeProvider theme={theme}>
<LocalizationProvider dateAdapter={DayJsUtils}>
{/* React-intl provider */}
<AppIntlProvider>
<CssBaseline />
<GlobalStyles />
{useScrollTop()}
<ToastContainer />
{routing}
</AppIntlProvider>
</LocalizationProvider>
</ThemeProvider>
</StylesProvider>
</AbilityContext.Provider>
</PersistGate>
);
};
export default App;
My DashboardLayout
const DashboardLayout: FC = () => {
const [isMobileNavOpen, setMobileNavOpen] = useState<boolean>(true);
const classes = useStyles();
const onMobileToggle = () => {
setMobileNavOpen(!isMobileNavOpen);
};
const onMobileOpen = () => {
setMobileNavOpen(true);
};
return (
<Box className={classes.root}>
<DashboardSidebar
onMobileToggle={onMobileToggle}
openMobile={isMobileNavOpen}
onMobileOpen={onMobileOpen}
/>
<Box className={classes.wrapper}>
<DashboardNavbar />
<Box className={classes.container}>
<Container
maxWidth="xl"
className={classes.content}
>
<Outlet />
</Container>
</Box>
</Box>
</Box>
);
};
export default DashboardLayout;
Related
I want to add icons inside a datagrid in a specific column.
But I don't even know if it's possible. If so, I want to use inside 'Role' column. I don't know how the implement it inside a datagrid. I searched in the web, but didn't get anything that helps me. So kindly help me figure this out.
this is my code
function DataGridExample() {
const [platform, setPlatform] = useState([]);
const [searchText, setSearchText] = useState('');
const [rows, setRows] = useState([]);
useEffect(() => {
let platformList = [
{ id: 1, role: 'Sender', counter_party: "Bharath", token: "1.000", date:"16-03-2022 06:20 AM", comments:'Test First Transfer' },
{ id: 2, role: "Sender", counter_party: "Harish", token: "1.000" , date:"14-03-2022 08:59 AM", comments:'Testing from hosted'},
{ id: 3, role: "Receiver", counter_party: "Vijay", token: "1.000", date:"14-03-2022 08:53 AM", comments:'Test First Transfer'},
];
setPlatform(platformList);
setRows(platformList);
}, []);
const columns = [
{ field: 'role', headerName: 'Role', width: 150,},
{ field: 'counter_party', headerName: 'Counter Party', width: 200 },
{ field: 'token', headerName: 'Token', width: 150 },
{ field: 'date', headerName: 'Date', width: 200 },
{ field: 'comments', headerName: 'Comments', width: 200 }
];
function escapeRegExp(value) {
return value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
}
const requestSearch = (searchValue) => {
const searchRegex = new RegExp(escapeRegExp(searchValue), 'i');
const filteredRows = platform.filter((row) => {
return Object.keys(row).some((field) => {
return searchRegex.test(row[field].toString());
});
});
setRows(filteredRows);
};
return (
<div>
<div style={{ height: 400, width: '100%' }}>
<Box>
<TextField
variant="outlined"
size='small'
value={searchText}
onChange={(e) => { setSearchText(e.target.value); requestSearch(e.target.value) }}
placeholder="Search..."
InputProps={{
startAdornment: <SearchIcon fontSize="small" color="action" />,
endAdornment: (
<IconButton
title="Clear"
aria-label="Clear"
size="small"
style={{ visibility: searchText ? 'visible' : 'hidden', borderRadius: "57%", paddingRight: "1px", margin: "0", fontSize: "1.25rem" }}
onClick={(e) => { setSearchText(''); setRows(platform) }}
>
<ClearIcon fontSize="small" color="action" />
</IconButton>
),
}}
/>
</Box>
<DataGrid
disableColumnMenu
rows={rows}
columns={columns}
pageSize={10}
rowsPerPageOptions={[10]}
/>
</div>
</div >
);
}
export { DataGridExample };
this is how my table currently looks like
and this is how I want my table to be
you should add custom renderCell in column
this is how i do it
enter image description here
Check the following to insert a material-ui icon in your datagrid.
import React, {useState, useEffect} from "react";
import { FormControlLabel, IconButton } from '#material-ui/core';
import { DataGrid } from "#material-ui/data-grid";
import EditIcon from '#material-ui/icons/Edit';
import { blue } from '#material-ui/core/colors';
const MatEdit = ({ index }) => {
const handleEditClick = () => {
// some action
}
return <FormControlLabel
control={
<IconButton color="secondary" aria-label="add an alarm" onClick={handleEditClick} >
<EditIcon style={{ color: blue[500] }} />
</IconButton>
}
/>
};
const MyComponent= () => {
const rows = [{ id: 1, name: "ABC", email: "xyz#gmail.com" }];
const columns=[
{ field: "name", headerName: "Name" },
{ field: "email", headerName: "Email" },
{
field: "actions",
headerName: "Actions",
sortable: false,
width: 140,
disableClickEventBubbling: true,
renderCell: (params) => {
return (
<div className="d-flex justify-content-between align-items-center" style={{ cursor: "pointer" }}>
<MatEdit index={params.row.id} />
</div>
);
}
}
];
return (
<div style={{ height: 500, width: 500 }}>
<DataGrid rows={rows} columns={columns} />
</div>
)
};
export default MyComponent;
Click here for a sandbox demo
I have created a sort of form and I want to pass a variable to the next screen when press submit.
var states = [
{label: "happy", value: 1},
{label: "sad", value: 2},
{label: "angry", value: 3},
{label: "relaxed", value: 4}
];
export default class App extends Component<Props> {
render() {
return (
<View style={styles.container}>
<Paragraph style={styles.textStyle}>How are you feeling today ?</Paragraph>
<RadioForm
radio_props={states}
initial={2}
onPress={(value) => {ToastAndroid.show(value.toString(), ToastAndroid.SHORT)}}
buttonSize={30}
buttonOuterSize={40}
selectedButtonColor={'blue'}
selectedLabelColor={'blue'}
labelStyle={{ fontSize: 15, }}
disabled={false}
formHorizontal={false}
/>
<Button title="Submit" onPress={() => this.props.navigation.navigate('ButtonsScreen')}/>
</View>
);
}
}
So, I want to pass variable "value" ( which the user selects ) to the 'ButtonsScreen'.
Anyone has any idea ?
Try this way
export default class App extends Component<Props> {
state = { val: "" }; // set state here
render() {
return (
<View style={styles.container}>
....
<RadioForm
....
onPress={(value) => {
this.setState({ val: value });
}}
....
/>
<Button
title="Submit"
onPress={() =>
this.props.navigation.navigate("ButtonsScreen", {
value: this.state.val,
})
}
/>
</View>
);
}
}
<FormControlLabel
control={
<Switch
onChange={(e) => changeSwitchState(e.target.name, e.target.checked)}
color='primary'
name='a'
/>
}
label="A"
/>
<FormControlLabel
control={
<Switch
onChange={(e) => changeSwitchState(e.target.name, e.target.checked)}
color='primary'
name='b'
/>
}
label="B"
/>
<FormControlLabel
control={
<Switch
onChange={(e) => changeSwitchState(e.target.name, e.target.checked)}
color='primary'
name='c'
/>
} label="C" />
<span>D</span>
<InputText
className={inputValidation(inputValues.e, inputValues.f, inputValues.d) ? 'err' : 'validated'}
id='d'
keyfilter="num"
value={inputValues.d}
onChange={e => changeInputValue(e.target.id, e.target.value)}
/>
<span>E</span>
<InputText
className={inputValidation(inputValues.f, inputValues.d, inputValues.e) ? 'errE' : 'validateE'}
id='e'
value={inputValues.e}
onChange={e => changeInputValue(e.target.id, e.target.value)}
mode="decimal"
useGrouping={false}
/>
)
};
here is mine code i want make code shorter and render this inputs and switch buttons by map way can someone explain how to do this and what is best practice and how to noth lost data which one im reciving by props way ?
Best way would to be to setup configuration arrays for this. Ideally you would want to keep your inputs in the "Controlled State" in React so your user interface always represents your state.
Lets first configure a constant which holds the initial configuration of your formControlLabels, which holds information I can read from your code which you supplied.
It might look something like this, and can be defined outside of the component which uses it. Arrays holding objects for each input is ideal, since later we want to use map to render these in your return method.
const formControlLabelConfig = [
{
color: "primary",
name: "a",
label: "A",
state: false
},
{
color: "primary",
name: "b",
label: "B",
state: false
},
{
color: "primary",
name: "c",
label: "C",
state: false
}
];
similiarly for your textInput components
const textInputConfig = [
{
keyFilter: "num",
id: "d",
mode: undefined,
className: "err",
errorClassName: "validated",
useGrouping: undefined,
value: ""
},
{
keyFilter: "num",
id: "e",
mode: "decimal",
className: "errE",
errorClassName: "validateE",
useGrouping: false,
value: ""
}
];
We can setup a state variable using this initial configuration. This would be within the functional component you are using to render the FormControlLabel and InputText components
const [formControlLabelState, setFormControlLabelState] = useState(formControlLabelConfig);
const [textInputConfig, setTextInputConfig] = useState(textInputConfig);
we can then use map to render each component according to its config. I have mocked up something of what you will end up with
import React, { useState } from "react";
const formControlLabelConfig = [
{
color: "primary",
name: "a",
label: "A",
state: false
},
{
color: "primary",
name: "b",
label: "B",
state: false
},
{
color: "primary",
name: "c",
label: "C",
state: false
}
];
const textInputConfig = [
{
keyFilter: "num",
id: "d",
mode: undefined,
className: "err",
errorClassName: "validated",
useGrouping: undefined,
value: ""
},
{
keyFilter: "num",
id: "e",
mode: "decimal",
className: "errE",
errorClassName: "validateE",
useGrouping: false,
value: ""
}
];
const SomeComponentName = () => {
const [formControlLabelState, setFormControlLabelState] = useState(
formControlLabelConfig
);
const [textInputState, setTextInputState] = useState(textInputConfig);
const getInputClassName = () => {
let className = "";
//return the className on validation
return className;
};
const changeInputValue = (id, value) => {
setTextInputState((prevState) => {
const newState = [...prevState];
const index = newState.findIndex((config) => config.id === id);
newState[index].value = value;
return newState;
});
};
const changeSwitchState = (name, chackedState) => {
setFormControlLabelState((prevState) => {
const newState = [...prevState];
const index = newState.findIndex((config) => config.name === name);
newState[index].state = chackedState;
return newState;
});
};
return (
<>
{formControlLabelState.map((config) => (
<FormControlLabel
key={config.id}
control={
<Switch
onChange={(e) =>
changeSwitchState(e.target.name, e.target.checked)
}
color={config.color}
name={config.name}
value={config.checked} //would need to check this. Not sure what attribute is used to set the checked state
/>
}
label="B"
/>
))}
<span>D</span>
{textInputState.map((config) => (
<InputText
key={config.id}
className={() => getInputClassName(config.id)}
id={config.id}
value={config.value}
onChange={(e) => changeInputValue(e.target.id, e.target.value)}
mode={config.mode}
useGrouping={config.useGrouping}
/>
))}
</>
);
};
I am working with antd cascader and want to add a prefix icon in the cascader. Although there is a provision for a suffix icon in the cascader I could not find a way to add a prefix icon.
import { Cascader } from 'antd';
const options = [
{
value: 'zhejiang',
label: 'Zhejiang',
children: [
{
value: 'hangzhou',
label: 'Hangzhou',
children: [
{
value: 'xihu',
label: 'West Lake',
},
],
},
],
},
{
value: 'jiangsu',
label: 'Jiangsu',
children: [
{
value: 'nanjing',
label: 'Nanjing',
children: [
{
value: 'zhonghuamen',
label: 'Zhong Hua Men',
},
],
},
],
},
];
function onChange(value) {
console.log(value);
}
ReactDOM.render(
<Cascader options={options} onChange={onChange} placeholder="Please select" />,
mountNode,
);
Currently, the cascader looks as :
I want it to look something similar to:
where the globe is a prefix icon. How could I add a prefix icon?
You can create a custom cascader with prefix/suffix icons of your choice if you use a wrapper div with relative positioning and have the <Icon/> child with absolute positioning and higher z-index than the Cascader/> (to go on top of it).
Check the example here: https://codesandbox.io/s/antd-cascader-ynqpk
const CustomCascader = ({ options, width = 300 }) => {
const [open, setOpen] = useState(false);
const onChange = value => {
console.log(value);
};
const filter = (inputValue, path) => {
return path.some(
option =>
option.display_name.toLowerCase().indexOf(inputValue.toLowerCase()) > -1
);
};
const onPopupVisibleChange = visible => {
setOpen(visible);
};
return (
<div style={{ position: "relative", width }}>
<Icon
type={open ? "up" : "down"}
style={{ position: "absolute", right: 8, top: 10, zIndex: 5 }}
/>
<Icon
type="global"
style={{ position: "absolute", left: 5, top: 10, zIndex: 5 }}
/>
<Cascader
style={{ paddingLeft: 0, width }}
suffixIcon={<div />}
expandTrigger="hover"
fieldNames={{ label: "name", value: "code", children: "items" }}
options={options}
onChange={onChange}
showSearch={{ filter }}
placeholder="Please select"
onPopupVisibleChange={onPopupVisibleChange}
popupVisible={open}
/>
</div>
);
};
ReactDOM.render(
<div>
<CustomCascader options={options} />
<CustomCascader options={options} />
<CustomCascader options={options} />
</div>,
document.getElementById("container")
);
I'm trying to connect a react-native program with some data from our SQL Server. Here is the Json string that our link returns:
[{"Item_ID":2,"first_name":"steve","last_name":"jones","phone":"510-712-1822","email":"sjones#waltersandwolf.com","company":"Glass"},{"Item_ID":4,"first_name":"Tina","last_name":"Wills","phone":"510-222-7788","email":"twills#waltersandwolf.com","company":"Glass","notes":"","json":"{fname: \"Tina\", lname: \"Wills\", phone: \"510-222-7788\", email: \"twills#waltersandwolf.com\", company: \"Glass\", project: \"Portal\"}"},{"Item_ID":5,"first_name":"Sleepy","last_name":"owl","phone":"555-555-5555","email":"owl#forest.com","company":"Forest","notes":"whoooooo","json":"{first_name:sleepy,last_name:owl, phone:55555555,company:Forest, email: owl, notes:whoooo}"}]
Using this code snippet I've found on the web, I'm trying to just get this to show up in a flatview but it is blank:
import React, { Component } from 'react';
import { AppRegistry, StyleSheet, FlatList, Text, View, Alert, ActivityIndicator, Platform} from 'react-native';
export default class App extends Component {
constructor(props)
{
super(props);
this.state = {
isLoading: true
}
}
componentDidMount() {
return fetch('https://functions-ww.azurewebsites.net/api/SteveListJSON')
.then((response) => response.json())
.then((responseJson) => {
this.setState({
isLoading: false,
dataSource: responseJson
}, function() {
// In this block you can do something with new state.
});
})
.catch((error) => {
console.error(error);
});
}
FlatListItemSeparator = () => {
return (
<View
style={{
height: 1,
width: "100%",
backgroundColor: "#607D8B",
}}
/>
);
}
GetFlatListItem (company) {
Alert.alert(company);
}
render() {
if (this.state.isLoading) {
return (
<View style={{flex: 1, paddingTop: 20}}>
<ActivityIndicator />
</View>
);
}
return (
<View style={styles.MainContainer}>
<FlatList
data={ this.state.dataSource }
ItemSeparatorComponent = {this.FlatListItemSeparator}
renderItem={({item}) => <Text style={styles.FlatListItemStyle} onPress={this.GetFlatListItem.bind(this, item.company)} > {item.company} </Text>}
keyExtractor={(item, index) => index.toString()}
/>
</View>
);
}
}
const styles = StyleSheet.create({
MainContainer :{
justifyContent: 'center',
flex:1,
margin: 10,
paddingTop: (Platform.OS === 'ios') ? 20 : 0,
},
FlatListItemStyle: {
padding: 10,
fontSize: 18,
height: 44,
},
});
I would appreciate any help you could provide. I'm new at this so it may be something simple I'm missing...
Url is returning response as string and the datasource you need is an object so before setting the state of datasource change it to an object.
Add this:--
this.setState({
isLoading: false,
dataSource: JSON.parse(responseJson)
}