How to dynamically show / hide the list of elements in a reaction

I'm having trouble showing / hiding some elements in the response. Basically, I have a dynamic list li, and inside li I have a label, when you click on li, I want to hide the label and show the input. Usually with jQuery it's as simple as

$('#element').hide() $('#element2').show()

I do not quite understand how to do this with my current layout

 class EntriesTable extends React.Component { constructor(props) { super(props); console.log(this.props.plannerId); this.state = { tasks: [], plannerId: this.props.plannerId, }; var state = this.state; } componentDidMount() { this.getTasks(this.state.plannerId); } EditTask(id) { console.log(id); var spanEl = id + 'taskSpan'; var inputEl = id + 'taskInput'; //hide this span //show input $(spanEl).hide(); $(inputEl).show(); //when save //hide input //update task //show span } updateTask(id, name) { $.ajax({ type: "GET", url: "/Task/Update", data: { id: id, name: name }, contentType: "application/json; charset=utf-8", success: function (data) { console.log(data); //this.setState({ tasks: data.ReturnObject, loading: false }); }.bind(this), error: function (xhr, status, err) { console.log(err); } }); } createTask(name) { //make api call to create planner here. var data = { Name: name, PlannerId: model.plannerId, Status: "Not Complete", Description: "", Affiliation: "", Footprint: "", Created: new Date(), Modified: null, }; $.ajax({ type: "POST", url: "/Task/Add", data: JSON.stringify(data), contentType: "application/json; charset=utf-8", success: function (data) { console.log(data); this.getTasks(model.plannerId); }.bind(this), error: function (xhr, status, err) { console.log(err); } }); } getTasks(id) { this.setState({ tasks: [], loading: true }); $.ajax({ type: "GET", url: "/Task/GetAll", data: { id: id }, contentType: "application/json; charset=utf-8", success: function (data) { console.log(data); this.setState({ tasks: data.ReturnObject, loading: false }); }.bind(this), error: function (xhr, status, err) { console.log(err); } }); } render() { const tasks = this.state.tasks.map((task) => { var spanId = task.Id + "taskSpan"; var inputId = task.Id + "taskInput"; return ( <li key={task.Id} className="list-group-item" style={{minHeight: '50px'}}> <div className="pull-left" style={{width: '50%'}}> <span id={spanId} onClick={this.EditTask.bind(this, task.Id) }>{task.Name}</span> <input id={inputId} type="text" style={{ display: 'none' } } /> </div> <div className="pull-right" style={{marginTop: '-5px', width: '50%'}}> <div className="pull-right"> <button className="btn btn-default">Add</button> <button className="btn btn-default">Edit</button> </div> </div> </li> ); }); return ( <div className="table-wrapper"> <div className="task-container"> <h3>{this.props.rowName}</h3> </div> <ul id="tasksContainer"> {tasks} <li className="list-group-item list-group-item-last"><input type="button" value="Add Task" onClick={this.addTask.bind(this)} className="btn btn-success btn-override" /></li> </ul> </div> ); } }; 

I saw other SOs that tell you to use the variable and then show / hide by changing this variable, but I'm not sure if this is doable for my need, since I have a dynamic list, this is not just one element I'm trying show or hide.

+5
source share
2 answers

 class EntriesTable extends React.Component { constructor(props) { super(props); console.log(this.props.plannerId); this.state = { editableTasks: [], tasks: [], plannerId: this.props.plannerId, }; var state = this.state; /* This isn't completely necessary but usually it is recommended you * bind the class method in the constructor so it isn't bound on each * render */ this.EditTask = this.EditTask.bind(this); } componentDidMount() { this.getTasks(this.state.plannerId); } EditTask(id) { /* So jQuery and react are kind of at odds with each other on fundamentals * React is supposed to be declarative whereas jQuery is imperative. Using * jQuery and React together is typically discouraged unless there is a real * need for it. In React you are supposed to define how you want the UI to render * based on some variables. You have two options available to you props and state. * props are passed from the parent and are immutable. state is managed within that * component and is mutable. So we have added a variable called editableTasks to your * state that will contain an array of all editable tasks. Instead of trying to hide * or show items here, we are simply going to add the id of now editable task to that * array * */ var nextState = this.state; nextState.editableTasks.push(id); this.setState(nextState); } updateTask(id, name) { $.ajax({ type: "GET", url: "/Task/Update", data: { id: id, name: name }, contentType: "application/json; charset=utf-8", success: function (data) { console.log(data); //this.setState({ tasks: data.ReturnObject, loading: false }); }.bind(this), error: function (xhr, status, err) { console.log(err); } }); } createTask(name) { //make api call to create planner here. var data = { Name: name, PlannerId: model.plannerId, Status: "Not Complete", Description: "", Affiliation: "", Footprint: "", Created: new Date(), Modified: null, }; $.ajax({ type: "POST", url: "/Task/Add", data: JSON.stringify(data), contentType: "application/json; charset=utf-8", success: function (data) { console.log(data); this.getTasks(model.plannerId); }.bind(this), error: function (xhr, status, err) { console.log(err); } }); } getTasks(id) { this.setState({ tasks: [], loading: true }); $.ajax({ type: "GET", url: "/Task/GetAll", data: { id: id }, contentType: "application/json; charset=utf-8", success: function (data) { console.log(data); this.setState({ tasks: data.ReturnObject, loading: false }); }.bind(this), error: function (xhr, status, err) { console.log(err); } }); } render() { const tasks = this.state.tasks.map((task) => { var editable = this.state.editableTasks.filter(id => id === task.Id).length > 0; /* Now here we are going to check whether this item is editable * based on id. So we assign a variable that will eval to a bool * based on whether when you filter editableTasks to see if it contains * the current items id the length is greater than 0. * * Now below instead of applying some id attribute we are going to return either * the input or the span based on whether it is editable using a ternary operation * */ return ( <li key={task.Id} className="list-group-item" style={{minHeight: '50px'}}> <div className="pull-left" style={{width: '50%'}}> {editable ? <input type="text" /> : <span onClick={this.EditTask( task.Id)}>{task.Name}</span>} </div> <div className="pull-right" style={{marginTop: '-5px', width: '50%'}}> <div className="pull-right"> <button className="btn btn-default">Add</button> <button className="btn btn-default">Edit</button> </div> </div> </li> ); }); return ( <div className="table-wrapper"> <div className="task-container"> <h3>{this.props.rowName}</h3> </div> <ul id="tasksContainer"> {tasks} <li className="list-group-item list-group-item-last"><input type="button" value="Add Task" onClick={this.addTask.bind(this)} className="btn btn-success btn-override" /></li> </ul> </div> ); } }; 

Thus, the above should work on editing elements. Now it does not actually process their editing or returns them to an immutable state. But this should illustrate how you should follow this "jet path."

I urge you to abandon jQuery. jQuery is going to make your React code more complex to manage and make it more complex to take a responsive way. If you need something for ajax requests, there are many smaller libraries that are just as good (a superagent is recommended, but a quick google can lead you to many others)

Let me know if you have any other questions.

+1
source

To show dynamically show / hide the list of elements in the real implementation of Visible.js in your file:

 import React, { Component } from 'react' import { Link, Router } from 'react-router'; import { connect } from 'react-redux'; import { Card, CardActions, CardHeader, CardMedia, CardTitle, CardText } from 'material-ui/Card'; import { List, ListItem } from 'material-ui/List'; import Divider from 'material-ui/Divider'; import '../../../static/images/cms-img3.jpg'; import '../../../static/images/cms-img4.jpg'; import '../../../static/images/cms-img5.jpg'; import '../../../static/images/grid-list/vegetables-790022_640.jpg'; import '../../../static/images/grid-list/00-52-29-429_640.jpg'; import '../../../static/images/grid-list/burger-827309_640.jpg'; import '../../../static/images/grid-list/camera-813814_640.jpg'; import '../../../static/images/grid-list/morning-819362_640.jpg'; import '../../../static/images/grid-list/hats-829509_640.jpg'; import '../../../static/images/grid-list/honey-823614_640.jpg'; import '../../../static/images/grid-list/water-plant-821293_640.jpg'; import '../../../static/images/video.mp4'; import '../../../static/images/video123.mp4'; class VisibleData extends Component { constructor(props) { super(props); this.state = { items: [], }; this.onTodoClick = this.onTodoClick.bind(this); } componentDidMount() { fetch('http://new.anasource.com/team9/news-api/?operation=view') .then(result => result.json() .then(news => { this.setState({ items: news.news }); }) ); } componentWillMount() { window.onpopstate = (event) => { this.componentDidMount(); }; } onTodoClick(id) { this.setState({ items: this.state.items.filter(item => item.news_id == id) }); } render() { return ( <Data show={this.onTodoClick} items={this.state.items} /> ) } } class Data extends Component { onTodoClick(e, id) { this.props.show(id); } render() { return ( <div> {this.props.items.map(item => { const p = item.news_type == "image"; const r = item.news_type == "video"; return <Link to={"todo/#/" + item.news_id} key={item.news_id}> <Card onClick={(e) => this.onTodoClick(e, item.news_id)} style={{margin:15}}> <CardTitle title={item.news_title} subtitle={item.news_description}> <CardMedia> {p ? <img src={item.news_src_url} /> : null } </CardMedia> <CardMedia> {r ? <video controls><source src={item.news_src_url} type="video/mp4"/></video> : null } </CardMedia> <div className='date'>{item.news_created_date}</div> </CardTitle> </Card> </Link> }) } </div> ) } } export default VisibleData; 
+1
source

Source: https://habr.com/ru/post/1257366/


All Articles