onChange for input React JS makes typing render slow - javascript

I am making a React page which has a post and comments on the post. Now the onChange on being triggered re-renders the whole class which makes the typing in input slow.
Now, if the is declared in a separate class and the value entered in the input there can be sent to the main class for API call. But I am not able to do this. Can anyone help me?
Below is code for my comment section of the screen.
commentChange(html) {
this.setState({ post_comment: html})
}
<div className="post-comments">
<div className="post-comments-head">
<div>Comments ({this.state.comments.length})</div>
</div>
<div className="comments">
{this.createCommentList(this.state.comments2)}
</div>
</div>
<div className="post-commenting">
{this.state.reply == -1 ? <span>Comment as {this.state.name}</span>
: this.commentBy()}
<div className="write-comment-post">
<ReactQuill
data-gramm_editor="false"
onChange={this.commentChange}
value={this.state.post_comment}
className="post_comments_x"
placeholder="Write a comment"
ref={(ip) => this.myInp = ip}
autoFocus={true}
theme=""
/>
<div className="comments-submit">
<button className="submit-comment"
onClick={() => this.submitComment(this.state.reply)}
disabled={!enabledComment}>
Comment
</button>
</div>
</div>
</div>
The createCommentList function takes comments and returns a nested list of comments. Below is the section where new comment is added.
How to solve this because it is making typing a new comment very slow.

<div className="write-comment-post">
<ReactQuill
data-gramm_editor="false"
onChange={this.commentChange}
value={this.state.post_comment}
className="post_comments_x"
placeholder="Write a comment"
ref={(ip) => this.myInp = ip}
autoFocus={true}
theme=""
/>
create a seperate component for this
and only onn enter call parennt function else onchange it will trigger

Related

Trying to return a different color div after selecting option in form submit using React and Typescript

I am working on a to do list using React and Typescript. I am trying to return a different colored div when selecting a priority in the option select dropdown (prioritySelect). I have tucked in a function within the ToDoItem JSX Element. What I want to happen is for the prioritySelect component to change the background color of the div it is in "to-do-item" to signify importance.
I tried to add handleOptionsChange function and call it within the div return at the bottom but I keep running into errors when trying to add handleOptionsChange, I am not sure why.
//TODOITEM TO RETURN TO DO COMPONENT
`function ToDoItem(props: { toDo: ToDo; onDeleteToDo: any; prioritySelect: any;}) {`
///TRYING TO CREATE FUNCTION EXPRESSION THAT CALLS EVENT SET STATE FOR PRIORITY BELOW
`handleOptionsChange:any; setState:any;}) {
handleOptionsChange = (event: any) => {
props.setState({
option: event.target.value
});
}`
`return (
<div className="to-do-item" id="to-do-item">
<div className="checkbox-title-container">
<div className="check-title-div">
{Checkbox()}
<h2 className="to-do-title">{props.toDo.title}</h2>
</div>
<div id="delete-div">`
//PRIORITY OPTION SELECT BELOW
`<select name="Priority" className="select-field" value={props.prioritySelect.option} onChange={props.handleOptionsChange}>
<option className="important" value='1'>Important</option>
<option selected value='2'>Normal</option>
</select>
<button id="delete" onClick={props.onDeleteToDo}>
Delete
</button>
</div>
</div>
<div className="description-box">
<span className="description">{props.toDo.description}</span>
</div>
<br />
<span className="to-do-date">
{/* {props.toDo.duedate.toLocaleDateString()} */}
</span>
</div>
);
}`
I am trying to call handleOptionsChange when returning a JSX component below, I have taken out the rest of the components within the to-do-item div for the sake of readability
`<div className="to-do-item" id="to-do-item">
{prioritySelect={handleOptionsChange}} </div>
<div>`

The generated div table does not render

I am doing a React web app and trying to dynamically generate table based on the selected data (users from a time period). The user data is downloaded successfully. I am using the same approach in other page. However, this time it does not render.
Here is the code:
displayUsers(tableOfUsers) {
let table = tableOfUsers.map(user => {
return (
<div className="div-table-row-titles" key={user.name}>
<div className="div-table-col">{user.name}</div>
<div className="div-table-col">{user.surname}</div>
<div className="div-table-col">{user.email}</div>
<div className="div-table-col">{user.tel}</div>
<div className="div-table-col">{user.addedBy}</div>
</div>
);
});
return table;
}
render() {
const userData = null;
if (this.state.volunteers !== []) {
console.log("HELLO");
let userData = this.state.volunteers.map(user => {
return (
<div className="div-table-row-titles">
<div className="div-table-col">{user.name}</div>
<div className="div-table-col">{user.surname}</div>
<div className="div-table-col">{user.email}</div>
<div className="div-table-col">{user.tel}</div>
<div className="div-table-col">{user.addedBy}</div>
</div>
);
}); // this.displayUsers(this.state.volunteers);
console.log(userData);
userData = userData[0];
}
return (
<form id="form1">
<div>
<p>{this.props.startTime}</p>
</div>
<div className="div-table">
<div className="div-table-row-titles">
<div className="div-table-col" align="center">
Name
</div>
<div className="div-table-col" align="center">
Surname
</div>
<div className="div-table-col" align="center">
Email
</div>
<div className="div-table-col" align="center">
Tel. No.
</div>
<div className="div-table-col" align="center">
Volunteer
</div>
</div>
{userData}
</div>
</form>
);
}
The user data is there, it is properly ordered, the userData is not null (it is detected as [{...},{...}]). Yet, it does not display. Any ideas how could I fix it?
Thanks in advance!
------SOLUTION-------
I have found the problem. The user.addedBy was an object (addedBy had other properties), therefore React could not process it. Solved!
Without access to the project this is a bit challenging to debug. I would start by simplifying the problem.
First maybe look at what you are trying to accomplish and break out what can be reusable components (Cell, Row, Column, Columns, etc)
Start building each section one at a time so you can debug each part one step a time, such as if you have 5 volunteers can you get 5 rows to show up?
Can I ask why you are using divs instead of a table?
Is this issue due to scoping of let ??
Since let is block scoped and "let userData" is within the if block, it won't be available outside {}.
Could you please try declaring userData outside the if scope or using var??

ReactJS - state not updated or has not effect?

I'm creating so called recipe box, where you should be able to add/edit/delete recipes. Initial rendering part seems to be working fine, but I'm struggling when it comes to states and updating html depending what was changed: whether existing recipe was modified, deleted or new one added.
Currently I implemented state change trigger when recipe is edited. By reading various articles I came to conclusion that if you want to read values from another element when some other element is interacted (in my case from input element when button element is clicked), I need to add state to track input directly while it is typed and then use that state to trigger what I want (In my case I just use value from so called pending state and set to normal state when that button is pressed).
But it seems it is not working. Though I'm probably doing something wrong.
Here is the part I implemented states I talked about:
class RecipeComponent extends React.Component {
constructor(props){
super(props);
this.state = {
title: '',
pendingTitle: '',
ingredients: '',
pendingIngredients: '',
}
}
handleChange(e, key){
let obj = {};
obj[key] = e.target.value;
this.setState(obj);
}
handleClick(){
this.setState(
{title: this.pendingTitle, ingredients: this.pendingIngredients});
}
_renderModal(target, ctx){
return (
<div className="modal fade" id={target} role="dialog">
<div className="modal-dialog">
<div className="modal-content">
<div className="modal-header">
<button type="button" className="close" data-dismiss="modal">×</button>
<h4 className="modal-title">{ctx.title}</h4>
</div>
<div className="modal-body">
<div className="form-group">
<label htmlFor="title" className="control-label"><span>Recipe</span></label>
<input type="text" id="title" className="form-control" placeholder="Recipe Name" defaultValue={ctx.recipeTitle ? ctx.recipeTitle : ''}
onKeyUp={(e) => this.handleChange(e, 'pendingTitle')}
/>
</div>
<div className="form-group">
<label htmlFor="ingredients" className="control-label"><span>Ingredients</span></label>
<input type="text" id="ingredients" className="form-control" placeholder="Enter Ingredients, separated by commas" defaultValue={ctx.ingredients ? ctx.ingredients : ''}
onChange={(e) => this.handleChange(e, 'pendingIngredients')}
/>
</div>
</div>
<div className="modal-footer">
{/*Seems to not update state properly*/}
<button type="button" className="btn btn-primary" onClick={() => this.handleClick()} data-dismiss="modal">{ctx.title}</button>
<button type="button" className="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
);
}
...
...
{/*Here title from state is never set*/}
// Should this.state.title replace default title?
recipeTitle: this.state.title || recipe.title,
}
Full code can be found here (you can also test how it is currently working if it was hard to understand what I meant. Try to open any recipe, edit it and press button Edit Recipe and nothing will happen, recipe title will not be changed): https://codepen.io/andriusl/pen/LjxYQo
You directly accessed this.pendingTitle instead of this.state.pendingTitle. so change this to
handleClick(){
this.setState(
{title: this.state.pendingTitle, ingredients: this.state.pendingIngredients});
}
and change this code to
<a data-toggle="collapse" data-target={anchor_target}
href={anchor_target} className="collapsed">{this.state.title||recipe.title}

react js getting data from a input field

I'm very new to reactjs and I've using AngularJS upto now. Currently i'm trying to learn reactjs.
I have a html code like this
<div class="status_bar">
<div>
<label class="status_head">Post as: John Smith</label>
<input class= 'post_data_input' placeholder="I'm seeking feedback for..."/>
.
<div class="status_down">
<button class="public_btn">Public</button>
<button class="post_btn">Post</button>
<img class='cam_btn' src="img/cam.png" alt=""/>
</div>
</div>
</div>
I want to save whatever typed in the input field to an array and access that data from the array to show somewhere else. How can I do this in reactjs?
Thanks inadvance.
you can get it by two ways , either:
1- assign ref value myInput to input , and retrieve it by this.refs.myInput.value
2 - IF you are getting value on firing its own event , retrieve it by event.target.value
SAMPLE :
class App extends React.Component {
constructor() {
super(...arguments);
this.state= {};
}
//Method-1 : this.refs.myInput.value
onClick() {
alert('You enter : '+this.refs.myInput.value);
}
// METHOD-2 : event.target.value
onKeyUp(event) {
const value = event.target.value;
this.setState({inputSize: value.length || ''})
}
render() {
return (<div class="status_bar">
<div>
<label class="status_head">Post as: John Smith </label>
<input ref="myInput" className= 'post_data_input' placeholder="I'm seeking feedback for..." onKeyUp={this.onKeyUp.bind(this)} />
.<label>{this.state.inputSize}</label>
<div className="status_down">
<button className="public_btn" onClick={this.onClick.bind(this)}>Public</button>
<button className="post_btn" onClick={this.onClick.bind(this)}>Post</button>
<img className='cam_btn' src="img/cam.png" alt=""/>
</div>
</div>
</div>)
}
}
// -- Mount component
ReactDOM.render(<App />, document.querySelector('section'))
<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>
<section></section>

Rendering a dynamic input field in React

I have a quiz form here and would like to add input fields for questions when a user clicks the "Add a question" button.
I've been playing around with the code and have been able to populate the state object with some text. Obviously, the goal is to have this be an input component and then somehow rendering this to the screen.
What I'm struggling with is how to render an actual element to the page. I know it's done in the render method of the component just not exactly sure how.
I think I'm getting close. Any help would be appreciated. The code is below.
Thanks!
var QuizForm = React.createClass({
getInitialState : function() {
return { questions : [] }
},
createQuestion : function() {
this.state.questions.push("Test");
// Adds "Test" to state object.
this.setState({
questions : this.state.questions
});
},
render : function() {
return (
<div className="quiz-form well text-center">
<h1 className="header text-center">Quiz Form</h1>
<ul>
{/* Would like question inputs to show up here */}
</ul>
<button onClick={this.createQuestion} className="add-question-btn btn btn-primary" style={{ marginTop : 40 }}>Add Question</button>
</div>
);
}
Just map your this.state.questions array to the HTML element you want.
For instance, if you want to render <li> elements:
render : function() {
return (
<div className="quiz-form well text-center">
<h1 className="header text-center">Quiz Form</h1>
<ul> // magic happens now
{this.state.questions.map(function(state) {
return <li>{state}</li>
})}
</ul>
<button onClick={this.createQuestion}
className="add-question-btn btn btn-primary"
style={{ marginTop : 40 }}>Add Question</button>
</div>
);
}
See an example.
If you want to render <input> tags, you can use the same technique above, but be mindful of the fact that React treats it as a controlled component.
A React best practice would be to map your state.questions array to a dynamically generated HTML component such as:
render : function() {
return (
<div className="quiz-form well text-center">
<h1 className="header text-center">Quiz Form</h1>
<ul> // magic happens now
{this.state.questions.map(function(state) {
return <li key={state.someId}>{state.question}</li>
})}
</ul>
<button onClick={this.createQuestion}
className="add-question-btn btn btn-primary"
style={{ marginTop : 40 }}>Add Question</button>
</div>
);
}
Please keep in mind that when mapping and rendering dynamic objects in React it's always good to insert a key for each mapped object. So make sure to create that when you're creating the content.
Best Regards,

Categories

Resources