How to fix rerendering after select option from react multiple-select? - javascript

I can't solve why my input is rerendered when I dynamically add next input. In first step I click on select employe from multiple select and input is dynamically created with id and name of employee.Now I can add allocation for employee but when I add next employee. Allocation value of first employee is removed.
1.Step
2.Step
3.Step
4.Step
Component ProjectForm (I deleted some unnecessary parts of this code for this question )
export default class ProjectForm extends Component {
constructor(props) {
super(props);
const { project, timurProjects } = this.props;
this.state = {
employees:
project && project.currentEmployees ? project.currentEmployees : [],
technologies:
project && project.technologies
? project.technologies.map(mapToId)
: [],
allTimurProjects: timurProjects,
allocationValue:
project && project.currentEmployees ? project.currentEmployees : [],
projectTimur: null,
};
this.handleSubmit = this.handleSubmit.bind(this);
this.handleUpdateEmployees = this.handleUpdateEmployees.bind(this);
this.handleUpdateTechnologies = this.handleUpdateTechnologies.bind(this);
}
componentDidMount() {
const { project } = this.props;
const { allTimurProjects } = this.state;
this.setState({
projectTimur: allTimurProjects.find(projectTimur => {
return project ? projectTimur.code === project.code : false;
}),
});
}
handleSubmit = values => {
const { submitProjectForm, project, successText } = this.props;
const { employees, technologies, projectTimur } = this.state;
const value = {
...values,
code: projectTimur ? projectTimur.code : null,
projectManagerId: projectTimur
? projectTimur.projectManager.id
: values.projectManager,
};
return submitProjectForm(
value,
employees,
technologies,
(project && project.id) || null,
)
.then(res => {
displayNotification(successText, 'success');
const { id } = res.data.project;
browserHistory.push(`/projects/detail/${id}`);
})
.catch(error => {
throw new SubmissionError(error.response.data.error);
});
};
handleUpdateEmployees(employees) {
this.setState({
employees,
});
}
handleUpdateTechnologies(technologies) {
this.setState({
technologies,
});
}
handleUpdateAllocation = allocValue => {
console.log(allocValue, 'ALLOCAVALUE');
this.setState({
allocationValue: allocValue,
});
};
render() {
const {
projectData,
project,
handleSubmit,
error,
pristine,
submitting,
title,
submitText,
} = this.props;
const {
employees,
technologies,
projectTimur,
allTimurProjects,
allocationValue,
} = this.state;
const employeesPristine = isEqual(
employees,
project && project.currentEmployees ? project.currentEmployees : [],
);
const technologiesPristine = isEqual(
technologies,
project && project.technologies ? project.technologies.map(mapToId) : [],
);
const allocationValuePristine = isEqual(
allocationValue,
project && project.currentEmployees ? project.currentEmployees : [],
);
const formPristine =
employeesPristine &&
technologiesPristine &&
pristine &&
allocationValuePristine;
const defaultPMValue = projectTimur
? projectTimur.projectManager.name
: '--';
const owners =
projectTimur && projectTimur.owner.name ? [projectTimur.owner] : [];
const projectManagers = projectTimur
? [projectTimur.projectManager]
: projectData.projectManagers;
return (
<Container>
<Row>
<Col>
<Card className="card-project-add hs-box-shadow mx-auto">
<CardHeader>
{project ? (
<Row>
<Col>
<FontAwesome icon={['fab', 'product-hunt']} /> {title}
</Col>
<Col className="text-right">
<Link to={`/projects/detail/${project.id}`}>
Show project detail
</Link>
</Col>
</Row>
) : (
<span>
<FontAwesome icon={['fab', 'product-hunt']} /> {title}
</span>
)}
</CardHeader>
<CardBody>
{error && <Alert color="danger">{error}</Alert>}
<Form
onSubmit={handleSubmit(this.handleSubmit)}
onKeyPress={blockSubmitOnEnter}
>
<FormRow>
</Col>
<Col xs="12" lg="5">
<Employees
title="Project employees"
employees={projectData.employees}
defaultValue={
(project && project.currentEmployees) || []
}
onUpdate={this.handleUpdateEmployees}
/>
<EmployeeAllocationTable
title="Project skills/technologies"
employees={employees}
project={project}
onUpdateAllocation={this.handleUpdateAllocation}
defaultValue={
(project && project.currentEmployees) || []
}
/>
</Col>
</FormRow>
<FormRow>
<Col xs="12" md="4" lg="3">
<Button
block
color="success"
type="submit"
disabled={formPristine || submitting}
>
{submitText}
</Button>
</Col>
<Col className="text-md-right mt-3 mt-md-2">
<RequiredFieldsNote />
</Col>
</FormRow>
</Form>
</CardBody>
</Card>
</Col>
</Row>
</Container>
);
}
}
Component Employee
import PropTypes from 'prop-types';
import Select from 'react-select';
import { FormGroup } from 'reactstrap';
import { getFilteredEmployees } from '../../../util/employees';
class Employees extends Component {
handleChange(selectedOptions) {
const { onUpdate } = this.props;
onUpdate &&
onUpdate(
selectedOptions.map(option => ({
id: option.value,
label: option.label,
})),
console.log(selectedOptions, 'SEL'),
);
}
render() {
const { title, employees } = this.props;
let { defaultValue } = this.props;
defaultValue = defaultValue.map(employee => ({
value: employee.id,
label: employee.fullNameInverted || '[unknown name]',
allocationValue: employee.allocationValue,
}));
console.log(defaultValue, 'DV');
const filteredEmployees = getFilteredEmployees(employees);
const options = filteredEmployees.map(employee => ({
value: employee.id,
label: employee.fullNameInverted,
allocationValue: employee.allocationValue,
}));
return (
<FormGroup>
<label>{title}</label>
<Select
defaultValue={defaultValue}
isMulti
options={options}
onChange={this.handleChange.bind(this)}
/>
</FormGroup>
);
}
}
Employees.propTypes = {
title: PropTypes.any,
employees: PropTypes.array.isRequired,
defaultValue: PropTypes.array,
onUpdate: PropTypes.func,
};
export default Employees;
Component.EmployeeAllocationTable
import { Table, Input } from 'reactstrap';
export default class EmployeeAllocationTable extends Component {
constructor(props) {
super(props);
let { defaultValue } = this.props;
defaultValue = defaultValue.map(employee => ({
value: employee.id,
label: employee.fullNameInverted || '[unknown name]',
allocationValue: employee.allocationValue,
}));
this.state = {
value: defaultValue,
key: defaultValue,
allocationValue: '',
};
console.log('State', this.state);
}
handleChangeInput = e => {
const { employees } = this.props;
const { name, value } = e.target;
console.log(name, 'Name', value, 'Value');
const employeesList =
employees &&
employees.find(
employeeLabel => employeeLabel.id.toString() === e.target.name,
);
employeesList.allocationValue = e.target.value;
e.preventDefault();
this.props.onUpdateAllocation(employeesList.allocationValue);
this.setState({
[name]: value,
});
};
render() {
const { employees } = this.props;
const newEmployeesTable =
employees &&
employees.map(employee => {
const employeesList =
employees &&
employees.find(employeeLabel => employeeLabel.id === employee.id);
return (
<tr key={employee.id}>
<td>{employeesList.fullName || employeesList.label}</td>
<td>{employeesList.allocationValue} %</td>
<td>
<Input
name={employee.id.toString()}
value={employee.allocationValue}
onChange={this.handleChangeInput}
placeholder="Allocation on the project (%) "
maxLength="3"
/>
</td>
</tr>
);
});
return (
<div>
<Table>
<thead>
<tr>
<th>Name</th>
<th>Allocation on the project</th>
</tr>
</thead>
<tbody>{newEmployeesTable}</tbody>
</Table>
</div>
);
}
}

What is this?
const employeesList =
employees &&
employees.find(employeeLabel => employeeLabel.id === employee.id);
upd: if you dont want to rerender table you should not call onUpdate prop (handleUpdateEmployees) from on Select change
also you can do something with object
onUpdate(
selectedOptions.map(option => ({
id: option.value,
label: option.label,
//add here allocation and input value
})),

Related

How to access attribute of a function in another component in reactjs

I want to get an attribute from a function within a component. The function is called checkbox.js:
export default function Checkboxes() {
const [checked, setChecked] = React.useState(false);
const handleChange = (event) => {
setChecked(event.target.checked);
};
return (
<div>
<Checkbox
checked={checked}
onChange={handleChange}
color="primary"
inputProps={{ 'aria-label': 'primary checkbox' }}
/>
</div>
);
}
The component Checkbox multiple times in a table row. props.characterData is an array that has various attributes.
const TableBody = props => {
const rows = props.characterData.map((row, index) => {
return (
<tr key={index}>
<td>
<Checkbox />
</td>
<td>{row.task}</td>
<td>{row.desc}</td>
</tr>
)
})
return <tbody>{rows}</tbody>
}
What I want to do is to save the "checked" boolean value into the row.checked attribute every time it is changed, but nothing I have tried or searched up worked.
The row.checked comes from an array of characters where each character is initialized in the form:
{ task: '', desc: '', checked: false}
In the TableBody, it is mapped for each element in the array.
Any help would be greatly appreciated.
import React, { useState, useEffect } from 'react'
const Checkboxes =({checked, cbOnChange})=> {
const handleChange = (event) => {
cbOnChange(event.target.checked);
};
return (
<div>
<Checkbox
checked={checked}
onChange={handleChange}
color="primary"
inputProps={{ 'aria-label': 'primary checkbox' }}
/>
</div>
);
}
const TableBody = props => {
const [checkboxValue, setCheckboxValue] = useState({})
useEffect(() => {
setCheckboxValue({})
}, [JSON.stringify(props.characterData)])
const handleChange =(index, checked)=>{
setCheckboxValue((state)=>({
...state,
[index]: checked
}))
}
const rows = props.characterData.map((row, index) => {
return (
<tr key={index}>
<td>
<Checkboxes cbOnChange={(checked)=> handleChange(index, checked)} checked={checkboxValue[index] || false}/>
</td>
<td>{row.task}</td>
<td>{row.desc}</td>
</tr>
)
})
return <tbody>{rows}</tbody>
}
export default TableBody
you should write like this:
export default function App() {
const [characterData , setCharacterData] = React.useState([{
id: 1,
priority : true,
task: "task1",
desc: "desc1"
},
{
id: 2,
priority : false,
task: "task2",
desc: "desc2"
}])
const handleChangePriority = (id , value) => {
let cloneCharacterData = [...characterData]
const selectData = characterData.filter(itm => itm.id === id)[0];
const index = cloneCharacterData.findIndex(itm => itm.id === id)
selectData.priority = value;
cloneCharacterData[index] = selectData;
setCharacterData(cloneCharacterData)
}
return (
<div >
<TableBody characterData={characterData} handleChangeProps={handleChangePriority} />
</div>
);
}
TableBody:
const TableBody = props => {
const rows = props.characterData.map((row, index) => {
return (
<tr key={index}>
<td>
<Checkbox id={row.id} priority={row.priority} handleChangeProps={props.handleChangeProps} />
</td>
<td>{row.task}</td>
<td>{row.desc}</td>
</tr>
)
})
return <tbody>{rows}</tbody>
}
And Checkboxes:
export default function Checkboxes({priority , handleChangeProps , id}) {
// const [checked, setChecked] = React.useState(false);
const handleChange = event => {
// setChecked(event.target.checked);
handleChangeProps(id , event.target.checked)
};
return (
<div>
<Checkbox
checked={priority}
onChange={handleChange}
color="primary"
inputProps={{ "aria-label": "primary checkbox" }}
/>
</div>
);
}

I need the below code written as React Hooks. Is it possible to write it so?

I am using react hooks mostly in my current app. I need the below code expressed as react hooks, without the this.state and this.props. My current app is expressed entirely as React Hooks. If you see it closely, the below code is writing out SQL query code with the click of a button. I need that functionality in my current app, but I don't know how to assimilate that in my app. Any ideas?
import React from 'react';
import { Row, Col, Tabs, Spin, Card, Alert, Tooltip, Icon, Button } from 'antd';
import cubejs from '#cubejs-client/core';
import { QueryRenderer } from '#cubejs-client/react';
import sqlFormatter from "sql-formatter";
import JSONPretty from 'react-json-pretty';
import Prism from "prismjs";
import "./css/prism.css";
const HACKER_NEWS_DATASET_API_KEY = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpIjozODU5NH0.5wEbQo-VG2DEjR2nBpRpoJeIcE_oJqnrm78yUo9lasw'
class PrismCode extends React.Component {
componentDidMount() {
Prism.highlightAll();
}
componentDidUpdate() {
Prism.highlightAll();
}
render() {
return (
<pre>
<code className='language-javascript'>
{ this.props.code }
</code>
</pre>
)
}
}
const tabList = [{
key: 'code',
tab: 'Code'
}, {
key: 'sqlQuery',
tab: 'Generated SQL'
}, {
key: 'response',
tab: 'Response'
}];
class CodeExample extends React.Component {
constructor(props) {
super(props);
this.state = { activeTabKey: 'code' };
}
onTabChange(key) {
this.setState({ activeTabKey: key });
}
render() {
const { codeExample, resultSet, sqlQuery } = this.props;
const contentList = {
code: <PrismCode code={codeExample} />,
response: <PrismCode code={JSON.stringify(resultSet, null, 2)} />,
sqlQuery: <PrismCode code={sqlQuery && sqlFormatter.format(sqlQuery.sql())} />
};
return (<Card
type="inner"
tabList={tabList}
activeTabKey={this.state.activeTabKey}
onTabChange={(key) => { this.onTabChange(key, 'key'); }}
>
{ contentList[this.state.activeTabKey] }
</Card>);
}
}
const Loader = () => (
<div style={{textAlign: 'center', marginTop: "50px" }}>
<Spin size="large" />
</div>
)
const TabPane = Tabs.TabPane;
class Example extends React.Component {
constructor(props) {
super(props);
this.state = { showCode: false };
}
render() {
const { query, codeExample, render, title } = this.props;
return (
<QueryRenderer
query={query}
cubejsApi={cubejs(HACKER_NEWS_DATASET_API_KEY)}
loadSql
render={ ({ resultSet, sqlQuery, error, loadingState }) => {
if (error) {
return <Alert
message="Error occured while loading your query"
description={error.message}
type="error"
/>
}
if (resultSet && !loadingState.isLoading) {
return (<Card
title={title || "Example"}
extra={<Button
onClick={() => this.setState({ showCode: !this.state.showCode })}
icon="code"
size="small"
type={this.state.showCode ? 'primary' : 'default'}
>{this.state.showCode ? 'Hide Code' : 'Show Code'}</Button>}
>
{render({ resultSet, error })}
{this.state.showCode && <CodeExample resultSet={resultSet} codeExample={codeExample} sqlQuery={sqlQuery}/>}
</Card>);
}
return <Loader />
}}
/>
);
}
};
export default Example;
It's quite easy to convert a class to a functional component.
Remember these steps:
class => const
// Class
export class Example
// FC
export const Example
componentLifeCycles => useEffect
// Class lifecycle
componentDidMount() {
// logic here
}
// FC
useEffect(() => {
// logic here
})
render => return
// Class
render () {
return (<Component/>)
}
// FC
return (<Component />)`
constructor => useState
// Class
constructor(props) {
this.state.val = props.val
}
// FC
const [val, setVal] = useState(props.val)
setState => second arg from useState
// Class
constructor() {
this.state.val = val // constructor
}
this.setState({ val }) // class
// FC
const[val, setVal] = useState(null)
setVal("someVal")
TLDR: Solution
import React, { useEffect, useState } from "react"
import { Tabs, Spin, Card, Alert, Button } from "antd"
import cubejs from "#cubejs-client/core"
import { QueryRenderer } from "#cubejs-client/react"
import sqlFormatter from "sql-formatter"
import Prism from "prismjs"
import "./css/prism.css"
const HACKER_NEWS_DATASET_API_KEY =
"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpIjozODU5NH0.5wEbQo-VG2DEjR2nBpRpoJeIcE_oJqnrm78yUo9lasw"
const PrismCode: React.FC = ({ code }) => {
useEffect(() => {
Prism.highlightAll()
})
return (
<pre>
<code className="language-javascript">{code}</code>
</pre>
)
}
const TabList = [
{
key: "code",
tab: "Code",
},
{
key: "sqlQuery",
tab: "Generated SQL",
},
{
key: "response",
tab: "Response",
},
]
const CodeExample: React.FC = ( { codeExample, resultSet, sqlQuery } ) => {
const [activeTabKey, setActiveTab] = useState("code")
const onTabChange = (key) => setActiveTab(key)
const contentList = {
code: <PrismCode code={codeExample} />,
response: <PrismCode code={JSON.stringify(resultSet, null, 2)} />,
sqlQuery: (
<PrismCode code={sqlQuery && sqlFormatter.format(sqlQuery.sql())} />
),
}
return (
<Card
type="inner"
tabList={TabList}
activeTabKey={activeTabKey}
onTabChange={(key) => {
onTabChange(key)
}}
>
{contentList[activeTabKey]}
</Card>
)
}
const Loader = () => (
<div style={{ textAlign: "center", marginTop: "50px" }}>
<Spin size="large" />
</div>
)
const TabPane = Tabs.TabPane
const Example: React.FC = ({ query, codeExample, render, title }) => {
const [showCode, toggleCode] = useState(false)
return (
<QueryRenderer
query={query}
cubejsApi={cubejs(HACKER_NEWS_DATASET_API_KEY)}
loadSql
render={({ resultSet, sqlQuery, error, loadingState }) => {
if (error) {
return (
<Alert
message="Error occured while loading your query"
description={error.message}
type="error"
/>
)
}
if (resultSet && !loadingState.isLoading) {
return (
<Card
title={title || "Example"}
extra={
<Button
onClick={() =>
toggleCode(!this.state.showCode)
}
icon="code"
size="small"
type={showCode ? "primary" : "default"}
>
{showCode ? "Hide Code" : "Show Code"}
</Button>
}
>
{render({ resultSet, error })}
{showCode && (
<CodeExample
resultSet={resultSet}
codeExample={codeExample}
sqlQuery={sqlQuery}
/>
)}
</Card>
)
}
return <Loader />
}}
/>
)
}
export default Example

React Bottleneck TextInput Inputfield

I've got a big react app (with Redux) here that has a huge bottleneck.
We have implemented a product search by using product number or product name and this search is extremely laggy.
Problem: If a user types in some characters, those characters are shown in the InputField really retarded. The UI is frozen for a couple of seconds.
In Internet Explorer 11, the search is almost unusable.
It's a Material UI TextField that filters products.
What I already did for optimization:
Replaced things like style={{
maxHeight: 230,
overflowY: 'scroll',
}} with const cssStyle={..}
Changed some critical components from React.Component to React.PureComponent
Added shouldComponentUpdate for our SearchComponent
Removed some unnecessary closure bindings
Removed some unnecessary objects
Removed all console.log()
Added debouncing for the input field (that makes it even worse)
That's how our SearchComponent looks like at the moment:
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import Downshift from 'downshift';
import TextField from '#material-ui/core/TextField';
import MenuItem from '#material-ui/core/MenuItem';
import Paper from '#material-ui/core/Paper';
import IconTooltip from '../helper/icon-tooltip';
import { translate } from '../../utils/translations';
const propTypes = {
values: PropTypes.arrayOf(PropTypes.shape({})).isRequired,
legend: PropTypes.string,
helpText: PropTypes.string,
onFilter: PropTypes.func.isRequired,
selected: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
isItemAvailable: PropTypes.func,
};
const defaultProps = {
legend: '',
helpText: '',
selected: '',
isItemAvailable: () => true,
};
const mapNullToDefault = selected =>
(selected === null || selected === undefined ? '' : selected);
const mapDefaultToNull = selected => (!selected.length ? null : selected);
class AutoSuggestField extends Component {
shouldComponentUpdate(nextProps) {
return this.props.selected !== nextProps.selected;
}
getLegendNode() {
const { legend, helpText } = this.props;
return (
<legend>
{legend}{' '}
{helpText && helpText.length > 0 ? (
<IconTooltip helpText={helpText} />
) : (
''
)}
</legend>
);
}
handleEvent(event) {
const { onFilter } = this.props;
const value = mapDefaultToNull(event.target.value);
onFilter(value);
}
handleOnSelect(itemId, item) {
const { onFilter } = this.props;
if (item) {
onFilter(item.label);
}
}
render() {
const { values, selected, isItemAvailable } = this.props;
const inputValue = mapNullToDefault(selected);
const paperCSSStyle = {
maxHeight: 230,
overflowY: 'scroll',
};
return (
<div>
<div>{this.getLegendNode()}</div>
<Downshift
inputValue={inputValue}
onSelect={(itemId) => {
const item = values.find(i => i.id === itemId);
this.handleOnSelect(itemId, item);
}}
>
{/* See children-function on https://github.com/downshift-js/downshift#children-function */}
{({
isOpen,
openMenu,
highlightedIndex,
getInputProps,
getMenuProps,
getItemProps,
ref,
}) => (
<div>
<TextField
className="searchFormInputField"
InputProps={{
inputRef: ref,
...getInputProps({
onFocus: () => openMenu(),
onChange: (event) => {
this.handleEvent(event);
},
}),
}}
fullWidth
value={inputValue}
placeholder={translate('filter.autosuggest.default')}
/>
<div {...getMenuProps()}>
{isOpen && values && values.length ? (
<React.Fragment>
<Paper style={paperCSSStyle}>
{values.map((suggestion, index) => {
const isHighlighted = highlightedIndex === index;
const isSelected = false;
return (
<MenuItem
{...getItemProps({ item: suggestion.id })}
key={suggestion.id}
selected={isSelected}
title={suggestion.label}
component="div"
disabled={!isItemAvailable(suggestion)}
style={{
fontWeight: isHighlighted ? 800 : 400,
}}
>
{suggestion.label}
</MenuItem>
);
})}
</Paper>
</React.Fragment>
) : (
''
)}
</div>
</div>
)}
</Downshift>
</div>
);
}
}
AutoSuggestField.propTypes = propTypes;
AutoSuggestField.defaultProps = defaultProps;
export default AutoSuggestField;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.5.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.5.0/umd/react-dom.production.min.js"></script>
It seems, that I did not find the performance problem as it still exists. Can someone help here?

React js redirect not redirecting

For some reason, I can't understand redirect is not working.
I don't get any error.
The Redirect is called from react-router-dom library
in the console I see the xxx.
** added **
for some reason the redirect returns an error
this is the redirect block:
redirectUser = (json) => {
console.log('json', json);
console.log('state', this.state);
if(this.state.auth == true){
localStorage.setItem('userid', json.userid);
localStorage.setItem('auth', this.state.auth);
console.log('xxx');
return <Redirect to='/biblist' />
}
}
this is the file data from chrome dev sources:
this is the entire component.
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import { connect } from 'react-redux';
import { Redirect, Link } from 'react-router-dom';
import {
Button,
Form,
FormGroup,
FormControl,
Col,
Alert,
Checkbox,
ControlLabel,
HelpBlock,
Grid,
Row
} from 'react-bootstrap';
import { userLogedIn } from '../../actions';
class LoginForm extends Component {
constructor() {
super();
this.state={
username: '',
password: '',
data: [],
auth: false,
usernameError: '',
passwordError: '',
EmptyUsernameError: '',
EmptyPasswordError: ''
}
this.onSubmitLogin = this.onSubmitLogin.bind(this);
this.onChange = this.onChange.bind(this);
}
componentWillMount(){
console.log('mount', this.props);
}
componentDidUpdate(){
console.log('Update', this.props);
console.log('Update username', this.props.userid);
}
clientValidate = () => {
let isError = false;
if(this.state.username === ''){
isError = true;
this.setState({EmptyUsernameError: 'לא הזנתם שם משתמש'});
}
if(this.state.password === ''){
isError = true;
this.setState({EmptyPasswordError: 'לא הזנתם סיסמה'});
}
return isError;
}
validate = () => {
let isError = false;
if(this.state.auth === false){
isError = true;
this.setState({usernameError: 'אחד הפרטים שהזנתם שגוי'});
}
return isError;
}
onSubmitLogin(event){
event.preventDefault();
if(this.clientValidate()){
this.clientValidate();
}else{
fetch('http://127.0.0.1/bibli/api/user_switch/' + this.state.username +
'/'+ this.state.password )
.then(response => response.json())
.then(json => {
if(json.count > 0)
{
this.setState({auth: true});
this.props.userLogedIn(json);
this.redirectUser(json);
}else{
let isError = true;
this.validate();
this.setState({
auth: false,
data: null
});
}
})
.catch(error => console.log('parsing faild', error))
}
}
redirectUser = (json) => {
console.log('json', json);
console.log('state', this.state);
if(this.state.auth == true){
localStorage.setItem('userid', json.userid);
localStorage.setItem('auth', this.state.auth);
console.log('xxx');
debugger
return <Redirect to='/biblist' />
}
}
onChange(event){
this.setState({
[event.target.name]: event.target.value,
auth: false,
usernameError: '',
EmptyPasswordError: '',
EmptyUsernameError: ''
})
}
render() {
return (
<Grid fluid id="LoginForm" className="yellow-bg">
<Row className="show-grid">
<Col xsOffset={2} xs={8} mdOffset={3} md={6}>
<h2 className="text-center">כבר רשומים? התחברו!</h2>
<Form horizontal>
<FormGroup controlId="formHorizontalusername">
<Col xs={12} sm={4}>
<FormControl ref="username" name="username" type="text" onChange={this.onChange} placeholder="הקלד דואר אלקטרוני"/>
</Col>
<Col xs={12} sm={4}>
<FormControl ref="password" name="password" type="password" onChange={this.onChange} placeholder="הקלד סיסמא"/>
</Col>
<Col xs={12} sm={4} >
<Button onClick={this.onSubmitLogin} type="submit" className="full-width-btn" id="loginSubmit">התחבר</Button>
</Col>
</FormGroup>
{
this.state.EmptyUsernameError ?
<Alert variant="danger"> {this.state.EmptyUsernameError} </Alert> :
''
}
{
this.state.EmptyPasswordError ?
<Alert variant="danger"> {this.state.EmptyPasswordError} </Alert> :
''
}
{
this.state.usernameError ?
<Alert variant="danger"> {this.state.usernameError} </Alert> :
''
}
<small><Link to="/register">אינך רשום? הרשם!</Link></small>
</Form>
</Col>
</Row>
</Grid>
);
}
}
const mapDispatchToProps = dispatch => {
return {
userLogedIn: (params) => dispatch(userLogedIn(params))
};
};
const mapStateToProps = state => {
return {
userid: state.authReducer.userid,
auth: state.authReducer.auth
}
}
export default connect(mapStateToProps, mapDispatchToProps)(LoginForm);
You could try with "withRouter" HOC
Example :
import { withRouter } from 'react-router-dom'
const Button = ({ history }) => (
<button
type='button'
onClick={() => { history.push('/new-location') }}
>
Click Me!
</button>
)
export default withRouter(Button)

DevExtreme React Grid

Anyone know how to change the fontSize of the TableHeaderRow in a DevExtreme React Grid?
Here's an example of code from the website (https://devexpress.github.io/devextreme-reactive/react/grid/demos/featured/data-editing/) that I have been working with
import * as React from 'react';
import {
SortingState, EditingState, PagingState,
IntegratedPaging, IntegratedSorting,
} from '#devexpress/dx-react-grid';
import {
Grid,
Table, TableHeaderRow, TableEditRow, TableEditColumn,
PagingPanel, DragDropProvider, TableColumnReordering,
} from '#devexpress/dx-react-grid-material-ui';
import Paper from '#material-ui/core/Paper';
import Dialog from '#material-ui/core/Dialog';
import DialogActions from '#material-ui/core/DialogActions';
import DialogContent from '#material-ui/core/DialogContent';
import DialogContentText from '#material-ui/core/DialogContentText';
import DialogTitle from '#material-ui/core/DialogTitle';
import Button from '#material-ui/core/Button';
import IconButton from '#material-ui/core/IconButton';
import Input from '#material-ui/core/Input';
import Select from '#material-ui/core/Select';
import MenuItem from '#material-ui/core/MenuItem';
import TableCell from '#material-ui/core/TableCell';
import DeleteIcon from '#material-ui/icons/Delete';
import EditIcon from '#material-ui/icons/Edit';
import SaveIcon from '#material-ui/icons/Save';
import CancelIcon from '#material-ui/icons/Cancel';
import { withStyles } from '#material-ui/core/styles';
import { ProgressBarCell } from '../../../theme-sources/material-ui/components/progress-bar-cell';
import { HighlightedCell } from '../../../theme-sources/material-ui/components/highlighted-cell';
import { CurrencyTypeProvider } from '../../../theme-sources/material-ui/components/currency-type-provider';
import { PercentTypeProvider } from '../../../theme-sources/material-ui/components/percent-type-provider';
import {
generateRows,
globalSalesValues,
} from '../../../demo-data/generator';
const styles = theme => ({
lookupEditCell: {
paddingTop: theme.spacing.unit * 0.875,
paddingRight: theme.spacing.unit,
paddingLeft: theme.spacing.unit,
},
dialog: {
width: 'calc(100% - 16px)',
},
inputRoot: {
width: '100%',
},
});
const AddButton = ({ onExecute }) => (
<div style={{ textAlign: 'center' }}>
<Button
color="primary"
onClick={onExecute}
title="Create new row"
>
New
</Button>
</div>
);
const EditButton = ({ onExecute }) => (
<IconButton onClick={onExecute} title="Edit row">
<EditIcon />
</IconButton>
);
const DeleteButton = ({ onExecute }) => (
<IconButton onClick={onExecute} title="Delete row">
<DeleteIcon />
</IconButton>
);
const CommitButton = ({ onExecute }) => (
<IconButton onClick={onExecute} title="Save changes">
<SaveIcon />
</IconButton>
);
const CancelButton = ({ onExecute }) => (
<IconButton color="secondary" onClick={onExecute} title="Cancel changes">
<CancelIcon />
</IconButton>
);
const commandComponents = {
add: AddButton,
edit: EditButton,
delete: DeleteButton,
commit: CommitButton,
cancel: CancelButton,
};
const Command = ({ id, onExecute }) => {
const CommandButton = commandComponents[id];
return (
<CommandButton
onExecute={onExecute}
/>
);
};
const availableValues = {
product: globalSalesValues.product,
region: globalSalesValues.region,
customer: globalSalesValues.customer,
};
const LookupEditCellBase = ({
availableColumnValues, value, onValueChange, classes,
}) => (
<TableCell
className={classes.lookupEditCell}
>
<Select
value={value}
onChange={event => onValueChange(event.target.value)}
input={(
<Input
classes={{ root: classes.inputRoot }}
/>
)}
>
{availableColumnValues.map(item => (
<MenuItem key={item} value={item}>
{item}
</MenuItem>
))}
</Select>
</TableCell>
);
export const LookupEditCell = withStyles(styles, { name: 'ControlledModeDemo' })(LookupEditCellBase);
const Cell = (props) => {
const { column } = props;
if (column.name === 'discount') {
return <ProgressBarCell {...props} />;
}
if (column.name === 'amount') {
return <HighlightedCell {...props} />;
}
return <Table.Cell {...props} />;
};
const EditCell = (props) => {
const { column } = props;
const availableColumnValues = availableValues[column.name];
if (availableColumnValues) {
return <LookupEditCell {...props} availableColumnValues={availableColumnValues} />;
}
return <TableEditRow.Cell {...props} />;
};
const getRowId = row => row.id;
class DemoBase extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
columns: [
{ name: 'product', title: 'Product' },
{ name: 'region', title: 'Region' },
{ name: 'amount', title: 'Sale Amount' },
{ name: 'discount', title: 'Discount' },
{ name: 'saleDate', title: 'Sale Date' },
{ name: 'customer', title: 'Customer' },
],
tableColumnExtensions: [
{ columnName: 'amount', align: 'right' },
],
rows: generateRows({
columnValues: { id: ({ index }) => index, ...globalSalesValues },
length: 12,
}),
sorting: [],
editingRowIds: [],
addedRows: [],
rowChanges: {},
currentPage: 0,
deletingRows: [],
pageSize: 0,
pageSizes: [5, 10, 0],
columnOrder: ['product', 'region', 'amount', 'discount', 'saleDate', 'customer'],
currencyColumns: ['amount'],
percentColumns: ['discount'],
};
const getStateDeletingRows = () => {
const { deletingRows } = this.state;
return deletingRows;
};
const getStateRows = () => {
const { rows } = this.state;
return rows;
};
this.changeSorting = sorting => this.setState({ sorting });
this.changeEditingRowIds = editingRowIds => this.setState({ editingRowIds });
this.changeAddedRows = addedRows => this.setState({
addedRows: addedRows.map(row => (Object.keys(row).length ? row : {
amount: 0,
discount: 0,
saleDate: new Date().toISOString().split('T')[0],
product: availableValues.product[0],
region: availableValues.region[0],
customer: availableValues.customer[0],
})),
});
this.changeRowChanges = rowChanges => this.setState({ rowChanges });
this.changeCurrentPage = currentPage => this.setState({ currentPage });
this.changePageSize = pageSize => this.setState({ pageSize });
this.commitChanges = ({ added, changed, deleted }) => {
let { rows } = this.state;
if (added) {
const startingAddedId = rows.length > 0 ? rows[rows.length - 1].id + 1 : 0;
rows = [
...rows,
...added.map((row, index) => ({
id: startingAddedId + index,
...row,
})),
];
}
if (changed) {
rows = rows.map(row => (changed[row.id] ? { ...row, ...changed[row.id] } : row));
}
this.setState({ rows, deletingRows: deleted || getStateDeletingRows() });
};
this.cancelDelete = () => this.setState({ deletingRows: [] });
this.deleteRows = () => {
const rows = getStateRows().slice();
getStateDeletingRows().forEach((rowId) => {
const index = rows.findIndex(row => row.id === rowId);
if (index > -1) {
rows.splice(index, 1);
}
});
this.setState({ rows, deletingRows: [] });
};
this.changeColumnOrder = (order) => {
this.setState({ columnOrder: order });
};
}
render() {
const {
classes,
} = this.props;
const {
rows,
columns,
tableColumnExtensions,
sorting,
editingRowIds,
addedRows,
rowChanges,
currentPage,
deletingRows,
pageSize,
pageSizes,
columnOrder,
currencyColumns,
percentColumns,
} = this.state;
return (
<Paper>
<Grid
rows={rows}
columns={columns}
getRowId={getRowId}
>
<SortingState
sorting={sorting}
onSortingChange={this.changeSorting}
/>
<PagingState
currentPage={currentPage}
onCurrentPageChange={this.changeCurrentPage}
pageSize={pageSize}
onPageSizeChange={this.changePageSize}
/>
<IntegratedSorting />
<IntegratedPaging />
<CurrencyTypeProvider for={currencyColumns} />
<PercentTypeProvider for={percentColumns} />
<EditingState
editingRowIds={editingRowIds}
onEditingRowIdsChange={this.changeEditingRowIds}
rowChanges={rowChanges}
onRowChangesChange={this.changeRowChanges}
addedRows={addedRows}
onAddedRowsChange={this.changeAddedRows}
onCommitChanges={this.commitChanges}
/>
<DragDropProvider />
<Table
columnExtensions={tableColumnExtensions}
cellComponent={Cell}
/>
<TableColumnReordering
order={columnOrder}
onOrderChange={this.changeColumnOrder}
/>
<TableHeaderRow showSortingControls />
<TableEditRow
cellComponent={EditCell}
/>
<TableEditColumn
width={120}
showAddCommand={!addedRows.length}
showEditCommand
showDeleteCommand
commandComponent={Command}
/>
<PagingPanel
pageSizes={pageSizes}
/>
</Grid>
<Dialog
open={!!deletingRows.length}
onClose={this.cancelDelete}
classes={{ paper: classes.dialog }}
>
<DialogTitle>
Delete Row
</DialogTitle>
<DialogContent>
<DialogContentText>
Are you sure to delete the following row?
</DialogContentText>
<Paper>
<Grid
rows={rows.filter(row => deletingRows.indexOf(row.id) > -1)}
columns={columns}
>
<CurrencyTypeProvider for={currencyColumns} />
<PercentTypeProvider for={percentColumns} />
<Table
columnExtensions={tableColumnExtensions}
cellComponent={Cell}
/>
<TableHeaderRow />
</Grid>
</Paper>
</DialogContent>
<DialogActions>
<Button onClick={this.cancelDelete} color="primary">
Cancel
</Button>
<Button onClick={this.deleteRows} color="secondary">
Delete
</Button>
</DialogActions>
</Dialog>
</Paper>
);
}
}
export default withStyles(styles, { name: 'ControlledModeDemo' })(DemoBase);
The font size of the text labelling the columns (e.g. product, region, amount) is fixed, and I see no parameters that can change it. Any ideas?
I think there are a few ways around this, the way I have used is having a fully controlled component.
Looks a little like this
<TableHeaderRow cellComponent={this.ExampleHeaderCell} />
Where ExampleHeaderCell is a component that would look something like this
ExampleHeaderCell = (props: any) => (<TableHeaderRow.Cell
className={exampleClass}
{...props}
key={column.name}
getMessage={() => column.title}
/>)
From there you can pass it a class as shown with exampleClass
You can take this further and have it customised for a particular column.
ExampleHeaderCells = (props: any) => {
const exampleClass = css({ backgroundColor: "blue" })
const { column } = props
if (column.name === "name") {
return (
<TableHeaderRow.Cell
className={exampleClass}
{...props}
key={column.name}
getMessage={() => column.title}
/>
)
}
return <TableHeaderRow.Cell {...props} key={column.name} getMessage={() => column.title} />
}
The example above is returning a specific cell with the exampleClass if the column name is equal to "name". Otherwise it just returns the regular TableHeaderRow.Cell

Categories

Resources