I am trying to make a Todo application but i am stuck,I am not able to proceed further. Please help
var Todo= React.createClass({
save() {
this.refs.newText.value
},
render(){
return(
<div className="list">
<h1> TO-DO List</h1>
<input type="text" ref="newtext" defaultValue={this.props.children} />
<button onclick={this.save} className="btn btn-primary glyphicon glyphicon-floppy-saved">
</button>
<ul>
<li>{this.target.value}</li>
</ul>
</div>
)
},
});
Maintain a state where in you will add the newly added item and then iterate over it to display in your view. Also you should not be using string refs, rather you should be going for ref callbacks as suggested by the react-docs. Also the onclick on button should be camelcase like onClick
var Todo= React.createClass({
getInitialState() {
return {
todos: []
}
},
save() {
var todos = [...this.state.todos];
todos.push(this.newText.value);
console.log(todos)
this.setState({todos});
},
render(){
return(
<div className="list">
<h1> TO-DO List</h1>
<input type="text" ref={(ip) => {this.newText = ip}}/>
<button onClick={this.save} className="btn btn-primary glyphicon glyphicon-floppy-saved">Save
</button>
<ul>
{this.state.todos.map(function(todo) {
return <li>{todo}</li>
})}
</ul>
</div>
)
},
});
ReactDOM.render(<Todo/>, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.2/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.2/react-dom.min.js"></script>
<div id="app"></div>
To add to Shubnam's answer, consider using ES6 classes and initializing the state in the constructor, since using ES6 classes is the recommended way now. React.createClass is now deprecated and shows a warning on the console. Check this code, notice that you will need to bind the save method.
Check these links for more info:
https://facebook.github.io/react/blog/#migrating-from-react.createclass
https://toddmotto.com/react-create-class-versus-component/
class Todo extends React.Component {
constructor(props) {
super(props);
this.state={todos:[]};
}
save() {
var todos = [...this.state.todos];
todos.push(this.newText.value);
this.setState({todos});
}
render(){
return(
<div className="list">
<h1> TO-DO List</h1>
<input type="text" ref={(ip) => {this.newText = ip}}/>
<button onClick={this.save.bind(this)} className="btn btn-primary glyphicon glyphicon-floppy-saved">Save
</button>
<ul>
{this.state.todos.map(function(todo) {
return <li>{todo}</li>
})}
</ul>
</div>
)
}
};
ReactDOM.render(<Todo/>, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>
``
import React, { Component } from 'react';
import Nav from './nav';
class Delete_Contect extends Component {
constructor(props)
{
super(props);
this.state={
name:'vishal',
name_add:[1,2,4]
};
this.Change = this.Change.bind(this);
this.Add_data = this.Add_data.bind(this);
}
Change()
{
this.setState(
{
name:'boss'
}
)
}
Add_data(e)
{
const newContect = this.newText.value
this.setState({
name_add: [...this.state.name_add, newContect]
})
}
render() {
return (
<div>
{this.state.name_add.map((number) => {
return(
<li>{number}</li>
)
})}
<input type="text" ref={(ip) => {this.newText = ip}} />
<button onClick={this.Add_data}>submit</button>
</div>
);
}
}
export default Delete_Contect;
Related
So, im trying to display my component named documentReader inside div with class desktop-app-grid by clicking and icon below, but icon is also a component, i tried doing this by using state, but i don't know how I can do this. I'm dropping my code below with hope someone can help me.
I got this:
<div className="desktop">
<div
className="desktop-app-grid"
>
</div>
<div className="taskbar">
<div className="taskbar-content">
<div className="apps">
<TaskbarAppIcon
appName="documentReader"
icon={icon}
title="My CV"
/>
</div>
<div className="status">
<Clock className="clock" />
</div>
</div>
</div>
</div>
);
}
And on click i want to get displayed in desktop-app-grid like this:
<div
className="desktop-app-grid"
>
<documentReader />
</div>
icon.js (code isn't complete)
class TaskbarAppIcon extends React.Component {
constructor() {
super();
this.state = {
clicked: false
};
this.handleClick = this.handleClick.bind(this);
}
handleClick = () => {
const icon = document.querySelector("img");
icon.classList.toggle("icon-active");
setTimeout(() => {
icon.classList.toggle("icon-active");
}, 200);
this.setState({
clicked: true
});
}
render(){
const classes = this.props.appName + "Icon icon";
return (
<div className={classes} onClick={this.handleClick}>
<img src={this.props.icon} alt={this.props.appName} title={this.props.title} className="icon-image"></img>
<div className="isActive"></div>
</div>
);
}
}
export default TaskbarAppIcon;
is there any function that works like innerHTML, but isn't a dangerouslyInnerHTML?
what you need to do is move your handleClick and clicked state to the parent component where you rendering TaskbarAppIcon. Being more specific where you have this code:
<div className="desktop">
<div className="desktop-app-grid">
</div>
<div className="taskbar">
<div className="taskbar-content">
<div className="apps">
<TaskbarAppIcon
appName="documentReader"
icon={icon}
title="My CV"
/>
</div>
<div className="status">
<Clock className="clock" />
</div>
</div>
</div>
</div>
So for example, the above code is in you App component, so you need to let it like this:
class App extends React.Component {
constructor() {
super();
this.state = {
clicked: false,
};
this.handleClick = this.handleClick.bind(this);
}
handleClick = () => {
const icon = document.querySelector("img");
icon.classList.toggle("icon-active");
setTimeout(() => {
icon.classList.toggle("icon-active");
}, 200);
this.setState({
clicked: !this.state.clicked,
});
};
render() {
return (
<div className="desktop">
<div className="desktop-app-grid">
// here's the trick, if your clicked state is TRUE it will show <documentReader />
{this.state.clicked && <documentReader />}
</div>
<div className="taskbar">
<div className="taskbar-content">
<div className="apps">
<TaskbarAppIcon
// Here you are specifying that TaskbarAppIcon has a prop handleClick and its a function
handleClick={this.handleClick}
appName="documentReader"
icon={icon}
title="My CV"
/>
</div>
</div>
</div>
</div>
);
}
}
And in your TaskbarAppIcon component you just need to change
<div className={classes} onClick={this.handleClick}>
to
<div className={classes} onClick={this.props.handleClick}>
I am trying to toggle the visibility of a div when clicking a seperate div. The problem is it sets the div invisible on the first click and only if it is visible to begin with. After that it just stays invisible and will not update. The state is still being toggled in the console however.
import React, { Component } from 'react';
import './App.css';
class App extends Component {
constructor(){
super()
this.state = {
vis: '0'
}
}
toghide=()=>{
console.log("toggle login", this.state.vis)
if(this.state.vis === "hidden"){
console.log('showing')
this.setState((state, props)=>({vis:'0'}))
} else {
console.log('hiding')
this.setState((state, props)=>({vis:'hidden'}))
}
}
render() {
const styles = {
visibility: this.state.vis
}
return (
<div className="App">
<div className="salebar"><a className="salebar sale"
href="login">Click here!</a></div>
<div className="navbar">
<div className="nav"><div className="nnav">JMZ</div></div>
<div className="nav2"><div className="nnav2">PRODUCTS</div></div>
<div className="loginContainer"><div className="login" onClick={this.toghide}>LOGIN/SIGN UP</div></div>
</div>
<div className="login-container">
<div className="lognester">
<div style={styles} className="login-tab">
<input className="user" type="text" placeholder="Username"/>
<input className="password" type="password" placeholder="Password"/>
<button className="user">Login</button>
Sign in or <a className="register-link" href="register">register</a> a new account.
</div>
</div>
</div>
<div className="intro-pics"></div>
<div className="content"></div>
<audio preload loop controls autoPlay className="audio">
<source src="https://memefly.me/i/toValhalla.mp3"/>
Your browser does not support the audio element.
</audio>
</div>
);
}
}
export default App;
Try this:
class App extends Component {
constructor() {
super();
this.state = {
vis: true
};
}
toghide = () => {
this.setState({ vis: !this.state.vis });
};
render() {
return (
<div className="App">
<div className="salebar">
<a className="salebar sale" href="login">
Click here
</a>
</div>
<div className="navbar">
<div className="nav">
<div className="nnav">JMZ</div>
</div>
<div className="nav2">
<div className="nnav2">PRODUCTS</div>
</div>
<div className="loginContainer">
<div className="login" onClick={this.toghide}>
LOGIN/SIGN UP
</div>
</div>
</div>
<div className="login-container">
<div className="lognester">
{this.state.vis ? (
<div className="login-tab">
<input className="user" type="text" placeholder="Username" />
<input
className="password"
type="password"
placeholder="Password"
/>
<button className="user">Login</button>
Sign in or{' '}
<a className="register-link" href="register">
register
</a>{' '}
a new account.
</div>
) : (
''
)}
</div>
</div>
<div className="intro-pics" />
<div className="content" />
</div>
);
}
}
export default App;
This is the demo: https://codesandbox.io/s/72zzk2xr70
Two things are wrong with your code
It should be visibility:visible not visibility: 0. So change that.
Never ever ever ever... set state in your render function, really really bad practice.
1 ) You can declare your togHide method above render such as
toghide = () => {
//your code
}
render(){...}
2) You may handle visibility condition better if you just use true/false boolean logic on your vis state. This can be as :
constructor(){
super()
this.state = {
vis: true
}
}
toghide = () => {
if(this.state.vis){
this.setState({
vis : false
})}
else{
this.setState({
vis : true
})}
3) In toghide method, you can use the code for setState I've used above. You don't have to pass props if you don't use any, and don't need to use return in setState.
In my react app I have this child component that inherits data from its parent. However, it does not update the page with new data from the child component when a relevant anchor link is clicked.
Here's my build - https://suite-search-lk.surge.sh/result/369523
From the link above if you click on a suggested card h1 element it just updates the URL with the id but does not update the page with the relevant card data from that id.
Any idea how I can fix this? Do I have to force the component to re-update?
Parent component (Card Wrapper)
class CardWrapper extends React.Component {
constructor(props) {
super(props);
this.state = {
stories: []
};
}
componentDidMount() {
axios
.get(API)
// .then(response => console.log(response))
// get our stories array, check it and then change state to contain our stories
.then(data => {
let stories;
if (data.data.stories && data.data.stories) {
if (Array.isArray(data.data.stories)) {
stories = data.data.stories;
} else {
stories = [data.data.stories];
}
} else {
stories = [];
}
this.setState({
stories: stories
});
});
}
render() {
return (
<CardWrapperDiv>
<div className="headingWrapper">
<div className="heading"> Suggested for you</div>
</div>
<Cards>
{this.state.stories.map(story => {
return (
<Card
title={story.content.title}
img={story.content.img}
description={story.content.description}
deadline={story.content.deadline_date}
tags={story.content.tags}
key={story.id}
id={story.id}
/>
);
})}
</Cards>
</CardWrapperDiv>
);
}
}
export default CardWrapper;
Child component
class Card extends React.Component {
render() {
return (
<CardDiv>
<div className="cardbox">
<div className="cardDetails">
<div className="headlineText">
<Link to={`/result/${this.props.id}`}> {this.props.title} </Link>
</div>
<div className="headlineSub">Colombo, Sri Lanka</div>
<div className="headlineDes">{this.props.description}</div>
<div className="textRemain">
{" "}
Deadline date: {this.props.deadline}
</div>
<div className="buttonRow">
<button className="downloadBtn">Download</button>
<button className="viewBtn">View</button>
</div>
</div>
<div className="cardimgwrapper">
<div className="cardimg">
<img src={this.props.img} alt="some title" />
</div>
</div>
</div>
</CardDiv>
);
}
}
export default Card;
Sorry it seems I have figured this out using the following post - Can you force a React component to rerender without calling setState?
Although I'm not exactly sure if it's the best way to go about it.
Essentially I used an OnClick listener to run a function and forces a re-render of the entire component.
Hope this can help someone else :)
class Card extends React.Component {
handleButtonClick() {
this.forceUpdate();
}
render() {
return (
<CardDiv>
<div className="cardbox">
<div className="cardDetails">
<div className="headlineText">
<Link to={`/result/${this.props.id}`} onClick={this.handleButtonClick}> {this.props.title} </Link>
</div>
<div className="headlineSub">Colombo, Sri Lanka</div>
<div className="headlineDes">{this.props.description}</div>
<div className="textRemain">
{" "}
Deadline date: {this.props.deadline}
</div>
<div className="buttonRow">
<button className="downloadBtn">Download</button>
<button className="viewBtn">View</button>
</div>
</div>
<div className="cardimgwrapper">
<div className="cardimg">
<img src={this.props.img} alt="some title" />
</div>
</div>
</div>
</CardDiv>
);
}
}
export default Card;
U have to use ur child component as a pure component. PureComponent Update when ur props change.
class Card extends React.PureComponent {
handleButtonClick() {
this.forceUpdate();
}
render() {
return (
<CardDiv>
.....
.....
</CardDiv>
);
}
}
export default Card;
Below is an example of me editing a "course" object in the database. Works perfectly fine on desktop but not on my iPhone. I'm unable to check on Android or other devices.
Not sure what more detail I could add but I need to since StackOverflow won't let me post until I use this filler. Please ignore this entire paragraph....
imports...
class EditCoursePage extends React.Component {
constructor(props, context) {
super(props, context);
this.state = {
name: this.props.name,
submitted: false,
_creator: {},
};
this.updateName = this.updateName.bind(this);
this.onSubmit = this.onSubmit.bind(this);
this.handleLogout = this.handleLogout.bind(this);
this.handleBack = this.handleBack.bind(this);
}
handleBack(event) {
window.location.href = `/courses/${this.props.match.params.cuid}`;
}
updateName(event) {
var input = event.target.value;
this.setState({
name: input,
});
}
componentWillMount() {
this.props.dispatch(actions.getCourse(this.props.match.params.cuid));
}
componentDidMount() {
this.props.dispatch(actions.getCourse(this.props.match.params.cuid));
}
onSubmit(event) {
const name = this.state.name;
const instructor = cookies.get('instructor')._id;
console.log(cookies.get('instructor')._id);
this.setState({
submitted: true,
});
this.props.dispatch(actions.editCourse(name,this.props.match.params.cuid));
console.log(this.props.name);
console.log(name, cookies.get('instructor')._id);
}
render() {
if (this.state.submitted) {
window.location.href = `https://young-mountain-65748.herokuapp.com/courses/${this.props.match.params.cuid}`;
}
return (
<div className="edit-course-form">
<div className="menu">
<Menu>
<a
id="dashboard-return"
className="menu-item"
href={`/courses/${this.props.match.params.cuid}`}
>
Back to Your Course
</a>
<a id="dashboard-logout" className="menu-item" href="/login">
Logout
</a>
</Menu>
</div>
<div className="mobile-header">
<div className="mobile-name">{this.props.name}</div>
</div>
<div className="edit-course-nav-options">
<div className="course-app-name">School Management App</div>
<ul>
<li>
<Link to="/login" onClick={this.handleLogout}>Log out </Link>
</li>
<li>
<Link to={`/courses/${this.props.match.params.cuid}`}>
Back to Your Course
</Link>
</li>
</ul>
</div>
<div className="container">
<div className="edit-course-name"><h2>{this.props.name}</h2></div>
<div className="submitForm">
<div className="field-line">
<label htmlFor="coursename">New Course Name:</label>
<input
id="coursename"
name="coursename"
value={this.state.name}
onChange={this.updateName}
/>
</div>
</div>
</div>
<div className="edit-course-buttons">
<button className="edit-course" onClick={this.onSubmit}>
Edit Course
</button>
<button className="edit-course-back" onClick={this.handleBack}>
Back
</button>
</div>
</div>
);
}
}
const mapStateToProps = (state, props) => {
return {
name: state.course.course.name,
_creator: state.course._creator,
};
};
export default connect(mapStateToProps)(EditCoursePage);
Here i tried to change state using edit button. I'm not sure how to edit it with double click an then save it on clicking save button.I made save function but it is not working as directed. I need the new value to be updated in the list after clicking save
class App extends React.Component {
constructor(){
super();
this.state={
todo:[],
editing:false,
value: ''
};
};
entertodo(keypress){
var Todo=this.refs.inputodo.value;
if( keypress.charCode == 13 )
{
this.setState({
todo: this.state.todo.concat({Value:Todo, checked:false})
});
this.refs.inputodo.value=null;
};
};
todo(todo,i){
return (
<li className={todo.checked===true? 'line':'newtodo'}>
<div onClick={this.todoCompleted.bind(this, i)}>
<input type="checkbox" className="option-input checkbox" checked={todo.checked} />
<div key={todo.id} className="item">
{todo.Value}
<button onClick={this.edit.bind(this,i)} className="editmode">edit</button>
<span className="destroy" onClick={this.remove.bind(this, i)}>X</span>
</div>
</div>
</li>
);
};
remove(i){
this.state.todo.splice(i,1)
this.setState({todo:this.state.todo})
};
todoCompleted(i){
var todo=this.state.todo;
todo[i].checked =todo[i].checked? false:true;
this.setState({
todo:this.state.todo
});
};
allCompleted=()=>{
var todo = this.state.todo;
var _this = this
todo.forEach(function(item) {
item.className = _this.state.finished ? "newtodo" : "line"
item.checked = !_this.state.finished
})
this.setState({todo: todo, finished: !this.state.finished})
};
changeValue(e) {
this.setState({
value: this.state.value = e.target.value
});
}
edit(i){
var todo= this.state.todo
this.setState({
editing:true,
value: this.state.todo[i].Value
});
};
save(i){
var Todo=this.ref.edittodo.value
var todo=this.state.todo[i]
this.setState({
editing:false,
todo:this.state.todo.concat({Value:todo})
});
};
rendernormal() {
return (
<div>
<h1 id='heading'>todos</h1>
<div className="lines"></div>
<div>
<input type="text" ref= "inputodo" onKeyPress={this.entertodo.bind(this)}className="inputodo"placeholder='todos'/>
<span onClick={this.allCompleted}id="all">^</span>
</div>
<div className="mainapp">
<ul className="decor">
{this.state.todo.map(this.todo.bind(this))}
</ul>
</div>
</div>
);
};
renderform(todo,i) {
return (
<div>
<h1 id='heading'>todos</h1>
<div className="lines"></div>
<div>
<input type="text" ref= "edittodo" value={this.state.value} onChange={this.changeValue.bind(this)} className="editodo"placeholder='EDIT TODO'/>
<span onClick={this.allCompleted}id="all">^</span>
<button onClick={this.save.bind(this,i)}>save</button>
</div>
<div className="mainapp">
<ul className="decor">
{this.state.todo.map(this.todo.bind(this))}
</ul>
</div>
</div>
);
};
render(){
if (this.state.editing) {
return this.renderform()
}
else {
return this.rendernormal()
}
};
}
ReactDOM.render(<App/>,document.getElementById('app'));
.line {
text-decoration: line-through;
color: red;
}
.newtodo{
text-decoration: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.8/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.8/react-dom.min.js"></script>
<div id="app"></div>
I tried some ways but the error i got is cannot read property 'edittodo' of undefined
The problem is that this.ref is undefined in this line:
this.ref.edittodo.value
What you're looking for is this.refs (source):
this.refs.edittodo.value
What's better is to stop using the string as a ref, and use a callback, as explained in the link above:
<input type="text"
ref={(input) => this.edittodo = input}
value={this.state.value}
onChange={this.changeValue.bind(this)}
className="editodo"placeholder='EDIT TODO'/>
And then you can access the input like this:
this.edittodo