React.js, onclick handler not changing state of the component - node.js

I am developing an app using node.js and react.js. I am trying to change the state of a component using an onclickhandler. The state of the component is not changing once it is rendered on the browser. However , if I try to do an alert in the onclickhandler its working.What might be the issue?
Here is the component that I'm trying to render :
var Server = module.exports = React.createClass({
getInitialState: function() {
return {
readOnly:"readOnly",
}
},
onButtonClick: function() {
this.setState({readOnly: ""});
},
render: function render() {
return (
<Layout {...this.props}>
<div id='index'>
<h1>Hello {this.props.name}!</h1>
<button onClick={this.onButtonClick}>Click Me</button>
<input readOnly={this.state.readOnly} />
<br/>
<a href='/'>Click to go to an react-router rendered view</a>
</div>
</Layout>
);
}
});

You need to set readOnly true or fasle.
onButtonClick: function() {
this.setState({readOnly: true or false});
}
It should work.

Here is a way you could add or remove an attribute to an element
var Example = React.createClass({
getInitialState: function () {
return {
readOnly: true,
}
},
onButtonClick: function () {
this.setState({readOnly: !this.state.readOnly});
},
render: function render() {
return (
<div {...this.props}>
<div id='index'>
<h1>Hello {this.props.name}!</h1>
<button onClick={this.onButtonClick}>Click Me</button>
<input {...(this.state.readOnly) ? {readOnly: 'readOnly'} : {}} />
<br/>
<a href='/'>Click to go to an react-router rendered view</a>
</div>
</div>
);
}
});

In this answer input value is editable only if u click the button otherwise the value of the input is not editable. This is one of the most simple way to achieve this...
import React from 'react';
import ReactDOM from 'react-dom';
class Sample extends React.Component{
constructor(props){
super(props);
this.state={
inputValue:"praveen"
}
this.valueChange = this.valueChange.bind(this);
}
valueChange(e){
this.setState({inputValue: e.target.value})
}
render(){
return(
<div>
<input type="text" value={this.state.inputValue } />
<button type="button" onClick={this.valueChange}>Edit</button>
</div>
)
}
}
export default Sample;
ReactDOM.render(
<Sample />,
document.getElementById('root')
);

Related

how to solve this no-unused-vars error in NodeJS?

I am creating a todo app using MERN stack.I am new to MERN stack technology and I kindly neeed your help solving this error.I have provided the code for my app.js file and todo.js file.I can't clearly find the solution of this error anywhere on the internet.
I am getting this error while runnng the node js app using npm start command.
Compiled with warnings.
src\App.js
Line 4:8: 'Todo' is defined but never used no-unused-vars
Search for the keywords to learn more about each warning.
To ignore, add // eslint-disable-next-line to the line before.
App.js
import React from 'react';
import logo from './logo.svg';
import './App.css';
import Todo from './components/Todo.js';
function App() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
);
}
export default App;
Todo.js
import React, { Component } from 'react'
import axios from 'axios';
// eslint-disable-next-line
export class Todo extends Component {
constructor(props) {
super(props)
this.state = {
todos : [],
item : ""
}
}
changeHandler = (event) => {
this.setState({item: event.target.value})
}
clickHandler = (event) => {
event.preventDefault()
console.log(this.state.item)
axios({
method: 'post',
url: 'http://localhost:3000/',
data: {
todo: this.state.item,
}
});
this.setState({item:''})
}
componentDidMount() {
axios.get('http://localhost:3000/').then((response) => {
console.log(response.data.data)
let data = [];
console.log(response.data.data.length)
for(var i =0; i < response.data.data.length; i++){
data.push(response.data.data[i].todo)
}
this.setState({todos: data})
});
}
componentDidUpdate() {
axios.get('http://localhost:3000/').then((response) => {
console.log(response.data.data)
let data = [];
console.log(response.data.data.length)
for(var i =0; i < response.data.data.length; i++){
data.push(response.data.data[i].todo)
}
this.setState({todos: data})
});
}
render() {
return (
<div>
<input type="text" onChange={this.changeHandler}/>
<button type="submit" onClick={this.clickHandler}>add</button>
<div>
<ul>{this.state.todos.map((todo, index) => <li key={index}>{todo}</li>)}</ul>
</div>
</div>
)
}
}
export default Todo
That warning you are getting because even though you are importing Todo file in your App.js file but you aren't using it anywhere.Either try using it in App.js or remove the import(in case you don't need it).That should fix the warning.
Or add // eslint-disable-next-line just before the import Todo.. statement in App.js

Pass a valid time type usnig moment from React setState to postgres

I am new in coding and essentially in React. I am trying to create a human resource management system that will have an employee and an admin. I am now working on using an axios to post to knex postgres as db and nodejs.
I need help to pass in a correct value with format of "HH:mm:ss" to my backend taking time type.
This is my knex migration:
exports.up = function(knex) {
return knex.schema.createTable('undertime_overtime', (table) => {
table.increments('id').primary();
table.date('date_filed').notNullable(); //has to be default date now?
table.time('from_time').notNullable();
table.time('to_time').notNullable();
table.string('reason').notNullable();
table.integer('time_type').defaultTo(1);
table.boolean('isDeleted').defaultTo(0);
table.boolean('isAccepted').defaultTo(0);
table.timestamp('created_at').defaultTo(knex.fn.now());
table.timestamp('modified_at').defaultTo(null);
table.integer('created_by').unsigned().notNullable();
table.foreign('created_by').references('employees.id');
});
Here are the things I tried that did not work:
state = {
date_filed: new Date(),
from_time: moment().format("HH:mm:ss").toString(),
to_time: moment().format("HH:mm:ss"),
reason: '',
time_type: 1,
created_by: 1 //todo
};
handleFromTime = time => {
this.setState({
from_time: time.format("HH:mm:ss")
});
console.log(time("HH:mm:ss"));
};
Here is my component:
import React, { Component } from 'react';
import moment from 'moment';
import { Content, Row, Col, Box, Button } from 'adminlte-2-react';
import TimePicker from 'rc-time-picker';
import DatePicker from "react-datepicker";
import axios from 'axios'
import 'rc-time-picker/assets/index.css';
class OvertimeComponent extends Component {
state = {
date_filed: new Date(),
from_time: moment(),
to_time: moment(),
reason: '',
time_type: 1,
created_by: 1 //todo
};
handleChangeDateFiled = date => {
this.setState({
date_filed: date
});
console.log(date)
};
handleFromTime = time => {
this.setState({
from_time: time
});
console.log(time);
};
handleToTime = time => {
this.setState({
to_time: time
});
console.log(time.format('HH:mm:ss'));
};
handleReason = event => {
this.setState({
reason: event.target.value
})
console.log(event.target.value);
}
handleSubmit = event => {
console.log(`date-> ${this.state.date_filed} from ${this.state.from_time} to ${this.state.to_time} reason ${this.state.reason}`)
event.preventDefault()
axios.post('http://localhost:8080/api/time',this.state)
.then(response=> {
console.log(response);
}).catch(error => {
console.error(error);
})
}
footer = [
<Button key="btnSubmit" type="success" pullRight text="Submit" onClick={this.handleSubmit} />,
];
render() {
return (
<Content title="Overtime" subTitle="Requests" browserTitle="Overtime">
<Row>
<Col md={6}>
<Row>
<Col xs={12}>
<Box title="Overtime Application" type="primary" collapsable footer={this.footer}>
<div className="form-group">
<label>Date</label>
<div>
<DatePicker name="date_filed" selected={this.state.date_filed} onChange={this.handleChangeDateFiled}/>
</div>
</div>
<div className="form-group">
<label>From</label>
<div>
<TimePicker name="from_time" value={this.state.from_time} onChange={this.handleFromTime} />
</div>
</div>
<div className="form-group">
<label>To</label>
<div>
<TimePicker name="to_time" value={this.state.to_time} onChange={this.handleToTime} />
</div>
</div>
<div className="form-group">
<label>Reason</label>
<textarea type="text" name="reason" value={this.state.reason} onChange={this.handleReason} className="form-control" placeholder="Enter ..." />
</div>
</Box>
</Col>
</Row>
</Col>
<Col md={6}>
<Box title="Request Status" type="primary" collapsable>
<div className="form-group">
<label>todo</label>
</div>
</Box>
</Col>
</Row>
</Content>);
}
}
export default OvertimeComponent;
I found the issue. I should've touched the axios post to get the format I wanted from the moment object.
axios.post('http://localhost:8080/api/time',{
'date_filed':this.state.date_filed,
'from_time':this.state.from_time.format('HH:mm:ss'),
'to_time':this.state.to_time.format('HH:mm:ss'),
'reason':this.state.reason,
'created_by': 1 //todo
})

'You tried to redirect to the same route you're currently on: "/"' when using a Redirect component with state

I'm trying to create a small demo application with two pages, one and two. The user may navigate from page one to page two by pressing a button, but only if the location objects' state in the second page contains a key attribute. If it does not, then the user is redirected to one.
The problem I'm encountering is that when using a to object to redirect from one and pass state to two, React Router warns:
You tried to redirect to the same route you're currently on: "/"
This doesn't make sense to me, because I'm attempting to redirect the user from /one to /two, not / to /two.
App.js
import React, { Component } from 'react';
import './App.css';
import { NavLink, Redirect, Route, BrowserRouter as Router, Switch } from 'react-router-dom';
const App = () => (
<Router>
<div className="App">
<ul>
<li>
<NavLink to="/one">One</NavLink>
</li>
<li>
<NavLink to="/two">Two</NavLink>
</li>
</ul>
<Switch>
<Route path="/one" component={One} />
<Route path="/two" component={Two} />
</Switch>
</div>
</Router>
);
class One extends Component {
constructor(props) {
super(props);
this.state = {
shouldRedirect: false,
};
this.redirect = this.redirect.bind(this);
}
redirect() {
this.setState({
shouldRedirect: true,
});
}
render() {
const { shouldRedirect } = this.state;
if (shouldRedirect) {
return (
// Replacing the below Redirect with the following corrects the error,
// but then I'm unable to pass state to the second page.
// <Redirect to="/two" />
<Redirect
to={{
pathName: '/two',
state: {
key: 'Some data.',
},
}}
/>
);
}
return (
<div>
<h3>This is the first page.</h3>
<button type="button" onClick={this.redirect}>Click me to go to page two.</button>
</div>
);
}
}
class Two extends Component {
constructor(props) {
super(props);
this.state = {
shouldRedirect: false,
};
this.redirect = this.redirect.bind(this);
}
componentWillMount() {
const { location } = this.props;
if (location.state && location.state.key) {
const { key } = location.state;
this.key = key;
} else {
this.redirect();
}
}
redirect() {
this.setState({
shouldRedirect: true,
});
}
render() {
const { shouldRedirect } = this.state;
if (shouldRedirect) {
return (
<div>
<p>You&apos;re being redirected to the first page because a key was not provided.</p>
<Redirect to="/one" />
</div>
);
}
return (
<div>
<h3>This is the second page.</h3>
<p>The key you provided was "{this.key}".</p>
</div>
);
}
}
export default App;
App.css
.App {
text-align: center;
}
You are passing pathName instead of pathname. This should fix the issue.
Working example on code sandbox.
<Redirect
to={{
pathname: "/two",
state: {
key: "Some data."
}
}}
/>
You should not use the <Redirect> as an another route in the <switch>. It should be condition driver. Use the below link for the reference.
https://reacttraining.com/react-router/web/example/auth-workflow

Missing "key" prop for element. (ReactJS and TypeScript)

I am using below code for reactJS and typescript. While executing the commands I get below error.
I also added the import statement
import 'bootstrap/dist/css/bootstrap.min.css';
in Index.tsx.
Is there a way to fix this issue?
npm start
client/src/Results.tsx
(32,21): Missing "key" prop for element.
The file is as below "Results.tsx"
import * as React from 'react';
class Results extends React.Component<{}, any> {
constructor(props: any) {
super(props);
this.state = {
topics: [],
isLoading: false
};
}
componentDidMount() {
this.setState({isLoading: true});
fetch('http://localhost:8080/topics')
.then(response => response.json())
.then(data => this.setState({topics: data, isLoading: false}));
}
render() {
const {topics, isLoading} = this.state;
if (isLoading) {
return <p>Loading...</p>;
}
return (
<div>
<h2>Results List</h2>
{topics.map((topic: any) =>
<div className="panel panel-default">
<div className="panel-heading" key={topic.id}>{topic.name}</div>
<div className="panel-body" key={topic.id}>{topic.description}</div>
</div>
)}
</div>
);
}
}
export default Results;
You are rendering an array of elements, so React needs a key prop (see react docs) to identify elements and optimize things.
Add key={topic.id} to your jsx:
return (
<div>
<h2>Results List</h2>
{topics.map((topic: any) =>
<div className="panel panel-default" key={topic.id}>
<div className="panel-heading">{topic.name}</div>
<div className="panel-body">{topic.description}</div>
</div>
)}
</div>
);
This has helped me
React special props should not be accessed
https://deepscan.io/docs/rules/react-bad-special-props

Display response object from GET request on backend in react component

I am still figuring React out and have a question. I want to display some data that I am getting back from my mLab database. When I make the request in Postman to test request i get back the object full of data and now I want to display that data in my component.
Backend/server.js:
//this is tested and works in postman
app.get('/logs', function(req, res) {
user: req.user;
res.json();
});
React action:
export const GET_DATA_SUCCESS = 'GET_DATA_SUCCESS';
export const GET_DATA_TRIGGERED = 'GET_DATA_TRIGGERED';
export const GET_DATA_FAILURE = 'GET_DATA_FAILURE';
export function getData() {
const promise = fetch('http://localhost:8080/logs');
return {
onRequest: GET_DATA_TRIGGERED,
onSuccess: GET_DATA_SUCCESS,
onFailure: GET_DATA_FAILURE,
promise,
};
}
Component where I want to display:
import React from 'react';
import {Router, Route, Link, Redirect, withRouter} from 'react-router-dom';
import { getData } from '../actions/memory';
import { connect } from 'react-redux';
export class oldMemory extends React.Component {
oldSearch(e) {
e.preventDefault();
this.props.getData();
}
render() {
return(
<div className="old-info">
<Link to="/main"><h3 className="title-journey">Travel Journal</h3></Link>
<h4>Retrieve a Memory</h4>
<p className="get-info">Look back on an old place you have visited and
reminisce.</p>
<input className="search" type="text" name="search" placeholder="Search"
/>
<button onClick={this.oldSearch.bind(this)}>Get</button>
// would like data to show up here
</div>
)
}
}
export default connect(null, { getData })(oldMemory)
I would use a state to store the data and set the state after the getData promise is resolved. Then, in the render method, i map the state data to div elements and display them in the the component.
// I assume your result of get Data is an array of
// objects {id: number,date: string, memory: string}
// and that getData is a promise
class OldMemory extends React.Component {
constructor(props) {
super(props);
this.state = {
data: [],
}
}
oldSearch = (e) => {
e.preventDefault();
this.props.getData().then(data => {
// if data is null, or undefined set it to an empty array
this.setState({ data: data || [] });
})
}
render() {
// build data to div elements for display
const memories = this.state.data.map(d => <div>{d.date} - {d.memory}</div>)
return(
<div className="old-info">
<Link to="/main"><h3 className="title-journey">Travel Journal</h3></Link>
<h4>Retrieve a Memory</h4>
<p className="get-info">Look back on an old place you have visited and
reminisce.</p>
<input className="search" type="text" name="search" placeholder="Search"
/>
<button onClick={this.oldSearch}>Get</button>
// would like data to show up here
<div id="display-data">
{ memories }
</div>
</div>
</div>
);
}
}
export default connect(null, { getData })(OldMemory)

Resources