400, message: "No search query" in Spotify API - reactjs

I am trying to obtain a reply (a track list (json)) from the spotify API but I keep getting this error: {status: 400, message: "No search query"} this is my function in my spotify.api module:
search(term) {
const accessToken = Spotify.getAccessToken();
return fetch(`https://api.spotify.com/v1/search?type=TRACK&q=${term}`, {
headers: {
Authorization: `Bearer ${accessToken}`,
},
}).then(response => {
return response.json();
}).then(jsonResponse => {
if (!jsonResponse.tracks) {
return [];
}
return jsonResponse.tracks.items.map(track => ({
id: track.id,
name: track.name,
artist: track.artists[0].name,
album: track.album.name,
}));
});
},
This is app.js (main container component) where the state is at; these are within the class react constructor:
search(term) {
Spotify.search(term).then(searchResults => {
this.setState({
searchResults: searchResults
})
})
}
render() {
return (
<div>
<div className = "App" >
< SearchBar onSearch={this.search} />
<div className="App-playlist">
< SearchResults searchResults={this.state.searchResults}
onAdd={this.addTrack} />
< Playlist playlistName={this.state.playlistName}
playlistTracks={this.state.playlistTracks}
onRemove={this.removeTrack}
onNameChange={this.updatePlaylistName}
onSave={this.savePlaylist} />
</div>
</div>
</div>);
}
}
This is the searchBar.js component, where the input (or track) will be requested:
search() {
this.props.onSearch(this.state.term);
}
handleTermChange(event) {
this.setState = { term: event.target.value };
}
render() {
return (
<div className="SearchBar">
<input
onChange={this.handleTermChange}
placeholder="Enter A Song, Album, or Artist"
/>
<button className="SearchButton" onClick={this.search}>SEARCH</button>
</div>
);
}
}

Try changing this
handleTermChange(event) {
this.setState = { term: event.target.value };
}
To
handleTermChange(event) {
this.setState({ term: event.target.value });
}
Since you were not using the setState method correctly, you were calling the Spotify API with an empty term value, then you get the http 400 error.

Related

Formio React Edit function does not take variable or state

I'm creating a custom Formio app using React and I'm trying to create a component that we can use to open previously created forms for editing. I use the component from Formio, and then try to pull the components and pass them to the components attribute, but it keeps telling me it's undefined. However, if I stringify it, and even import it using a variable or paste the exact string in, it works, but if I try to pass it to a variable or state, it won't work. Below is my code and any help is much appreciated. I feel like I've tried everything.
import { FormEdit, FormBuilder } from "react-formio";
import axios from "axios";
import AppLayout from "../pages/layout/appLayout";
import { Typography } from "#material-ui/core/";
import { Link } from "react-router-dom";
import { components } from "../formData";
export default class FormUpdate extends React.Component {
state = {
formName: "",
formTitle: "",
isFormSubmitted: false,
formComponents: {},
errorMsg: "",
};
componentDidMount() {
console.log("Id", this.props.formData);
axios
.get(
`https://awsid.execute-api.us-east-1.amazonaws.com/prod/form?formName=${this.props.formData.id}`,
{ crossDomain: true },
{
headers: {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET,POST,OPTIONS",
},
}
)
.then((res) => {
console.log(res.data.form.components);
this.setState({
formComponents: res.data.form.components[0],
});
})
.catch((error) => {
console.log(error);
this.setState({ errorMsg: "Error retrieving form data." });
});
}
updateForm = (form) => {
const payload = {
form,
};
console.log("Form Data:", form);
/* Code to fix JSON of select boxes component. If no default value is selected, default value attribute is deleted */
for (var key in payload.form.components) {
if (
form.components[key].defaultValue === "" ||
form.components[key].defaultValue === null ||
// form.components[key].defaultValue === false ||
form.components[key].defaultValue.hasOwnProperty("")
) {
console.log(
form.components[key].defaultValue + " is blank. Deleting attribute."
);
delete form.components[key].defaultValue;
}
console.log(form.components[key].defaultValue);
}
return axios
.put(
`https://awsid.execute-api.us-east-1.amazonaws.com/prod/form`,
payload,
{ crossdomain: true },
{
headers: {
"Content-type": "application/json",
},
}
)
.then((response) => {
console.log("Uploaded", response.data);
this.setState({
formName: response.data.id,
formTitle: response.data.title,
isFormSubmitted: true,
});
})
.catch((error) => {
console.log("Did not post: " + error);
});
};
handleFormNameChange = (evt) => {
const value = evt.target.value;
this.setState({
...this.state,
formName: value,
});
};
handleFormNameClick = async () => {
await this.setState({
formNameForm: false,
});
this.retrieveData(this.state.formName);
// console.log(this.state.formName);
};
listComponents = () => {
this.state.formComponents.map((item) => {
console.log(item);
// this.setState({ formComponents: item });
return item;
});
};
components = JSON.stringify(this.state.formComponents).replace(
/^\[(.+)\]$/,
"$1"
);
render() {
// const components = JSON.stringify(this.state.formComponents).replace(
// /^\[(.+)\]$/,
// "$1"
// );
// const allComponents = this.state.formComponents[0];
console.log(
JSON.stringify(this.state.formComponents).replace(/^\[(.+)\]$/, "$1")
);
console.log(this.state.formComponents);
console.log(components);
return (
<AppLayout>
<div className="container">
<link rel="stylesheet" href="styles.css" />
<link
rel="stylesheet"
href="https://unpkg.com/formiojs#latest/dist/formio.full.min.css"
/>
<link
href="https://fonts.googleapis.com/css2?family=Bangers&display=swap"
rel="stylesheet"
></link>
<main className="formEditContainer">
{this.state.isFormSubmitted === true ? (
<div className="fadePanel">
<Typography variant="h4" align="center">
Form Completed
</Typography>
<br />
<Typography variant="body1" align="center">
<b>
<i> To view form visit:</i>
</b>{" "}
<Link
to={`/openform/${this.state.formName}`}
className="links"
>
<small>{this.state.formTitle}</small>
</Link>
</Typography>
</div>
) : (
<div>
<Typography>
Form Name:
{this.props.formData.id}
</Typography>
<br />
<FormEdit
form={{
display: "form",
title: this.props.formData.id,
name: this.props.formData.id,
path: this.props.formData.id,
components: [components],
}}
saveText={"Save Form"}
saveForm={(form) => this.updateForm(form)}
>
<FormBuilder
form={{
display: "form",
title: this.props.formData.id,
}}
Builder={{}}
onUpdateComponent={{}}
/>
</FormEdit>
</div>
)}
<br />
<br />
</main>
</div>
</AppLayout>
);
}
}

How to properly display JSON result in a table via ReactJS

I have this code which fetches data from an API and displays JSON response in a div. How do I display the JSON response in a table?
This is how I display it in div via status.jsx:
// some codings
render() {
const { status, isLocal } = this.props;
if(!isLocal()) {
return (
<div className="status">
<div className="status-text">
<b>Status</b> {status.text}<br />
<b>Title</b> status.textTitle} <br />
<b>Event</b> {status.textEvent}
</div>
</div>
)
}
}
I have tried displaying it in a table as per below but could not get it to be aligned properly
//some codings
render() {
const { status, isLocal } = this.props;
if(!isLocal()) {
return (
<table>
<tbody>
<th>Status</th>
<th>Title</th>
<th>Event</th>
<tr>
<td>{status.text} </td>
<td>{status.textTitle} </td>
<td>{status.textEvent}</td>
<td><button
className="btn btn-danger status-delete"
onClick={this.toggleDeleteConfirmation}
disabled={this.state.showDeleteConfirmation}
>
Delete
</button></td>
</tr></tbody>
</table>
)
}
}
Here is profile.jsx:
import React, { Component } from 'react';
import {
isSignInPending,
loadUserData,
Person,
getFile,
putFile,
lookupProfile
} from 'bs';
import Status from './Status.jsx';
const avatarFallbackImage = 'https://mysite/onename/avatar-placeholder.png';
const statusFileName = 'statuses.json';
export default class Profile extends Component {
constructor(props) {
super(props);
this.state = {
person: {
name() {
return 'Anonymous';
},
avatarUrl() {
return avatarFallbackImage;
},
},
username: "",
statuses: [],
statusIndex: 0,
isLoading: false
};
this.handleDelete = this.handleDelete.bind(this);
this.isLocal = this.isLocal.bind(this);
}
componentDidMount() {
this.fetchData()
}
handleDelete(id) {
const statuses = this.state.statuses.filter((status) => status.id !== id)
const options = { encrypt: false }
putFile(statusFileName, JSON.stringify(statuses), options)
.then(() => {
this.setState({
statuses
})
})
}
fetchData() {
if (this.isLocal()) {
this.setState({ isLoading: true })
const options = { decrypt: false, zoneFileLookupURL: 'https://myapi/v1/names/' }
getFile(statusFileName, options)
.then((file) => {
var statuses = JSON.parse(file || '[]')
this.setState({
person: new Person(loadUserData().profile),
username: loadUserData().username,
statusIndex: statuses.length,
statuses: statuses,
})
})
.finally(() => {
this.setState({ isLoading: false })
})
} else {
const username = this.props.match.params.username
this.setState({ isLoading: true })
lookupProfile(username)
.then((profile) => {
this.setState({
person: new Person(profile),
username: username
})
})
.catch((error) => {
console.log('could not resolve profile')
})
const options = { username: username, decrypt: false, zoneFileLookupURL: 'https://myapi/v1/names/'}
getFile(statusFileName, options)
.then((file) => {
var statuses = JSON.parse(file || '[]')
this.setState({
statusIndex: statuses.length,
statuses: statuses
})
})
.catch((error) => {
console.log('could not fetch statuses')
})
.finally(() => {
this.setState({ isLoading: false })
})
}
}
isLocal() {
return this.props.match.params.username ? false : true
}
render() {
const { handleSignOut } = this.props;
const { person } = this.state;
const { username } = this.state;
return (
!isSignInPending() && person ?
<div className="container">
<div className="row">
<div className="col-md-offset-3 col-md-6">
{this.isLocal() &&
<div className="new-status">
Hello
</div>
}
<div className="col-md-12 statuses">
{this.state.isLoading && <span>Loading...</span>}
{
this.state.statuses.map((status) => (
<Status
key={status.id}
status={status}
handleDelete={this.handleDelete}
isLocal={this.isLocal}
/>
))
}
</div>
</div>
</div>
</div> : null
);
}
}

Reactjs: How to properly fetch each users record from database on pop button click using Reactjs

The code below shows each user info on users list button click.
Now I want fetch each users record from database on users list button click.
In the open() function, I have implemented the code below
open = (id,name) => {
alert(id);
alert(name);
//start axios api call
const user_data = {
uid: 'id',
uname: 'name'
};
this.setState({ loading_image: true }, () => {
axios.post("http://localhost/data.php", { user_data })
.then(response => {
this.setState({
chatData1: response.data[0].id,
chatData: response.data,
loading_image: false
});
console.log(this.state.chatData);
alert(this.state.chatData1);
})
.catch(error => {
console.log(error);
});
});
}
In class OpenedUser(), I have initialize in the constructor the code below
chatData: []
In the render method have implemented the code
<b> Load Message from Database for each user ({this.state.chatData1})</b>
<div>
{this.state.chatData.map((pere, i) => (<li key={i}>{pere.lastname} - {pere.id}----- {pere.username}</li>))}
</div>
Here is my Issue:
My problem is that the Axios Api is getting the result but am not seeing any result in the render method.
but I can see it in the console as per code below
Array(1)
0: {id: "1", firstname: "faco", lastname: "facoyo"}
length: 1
Here is an example of json api response.
[{"id":"1","firstname":"faco","lastname":"facoyo"}]
Here is the full code
import React, { Component, Fragment } from "react";
import { render } from "react-dom";
import { Link } from 'react-router-dom';
import axios from 'axios';
class User extends React.Component {
open = () => this.props.open(this.props.data.id, this.props.data.name);
render() {
return (
<React.Fragment>
<div key={this.props.data.id}>
<button onClick={() => this.open(this.props.data.id,this.props.data.name)}>{this.props.data.name}</button>
</div>
</React.Fragment>
);
}
}
class OpenedUser extends React.Component {
constructor(props) {
super(props);
this.state = {
chatData: [],
hidden: false,
};
}
componentDidMount(){
} // close component didmount
toggleHidden = () =>
this.setState(prevState => ({ hidden: !prevState.hidden }));
close = () => this.props.close(this.props.data.id);
render() {
return (
<div key={this.props.data.id} style={{ display: "inline-block" }}>
<div className="msg_head">
<button onClick={this.close}>close</button>
<div>user {this.props.data.id}</div>
<div>name {this.props.data.name}</div>
{this.state.hidden ? null : (
<div className="msg_wrap">
<div className="msg_body">Message will appear here</div>
<b> Load Message from Database for each user ({this.state.chatData1}) </b>
<div>
{this.state.chatData.map((pere, i) => (
<li key={i}>
{pere.lastname} - {pere.id}----- {pere.username}
</li>
))}
</div>
</div>
)}
</div>
</div>
);
}
}
class App extends React.Component {
constructor() {
super();
this.state = {
shown: true,
activeIds: [],
data: [
{ id: 1, name: "user 1" },
{ id: 2, name: "user 2" },
{ id: 3, name: "user 3" },
{ id: 4, name: "user 4" },
{ id: 5, name: "user 5" }
],
};
}
toggle() {
this.setState({
shown: !this.state.shown
});
}
open = (id,name) => {
alert(id);
alert(name);
//start axios api call
const user_data = {
uid: 'id',
uname: 'name'
};
this.setState({ loading_image: true }, () => {
axios.post("http://localhost/apidb_react/search_data.php", { user_data })
.then(response => {
this.setState({
chatData1: response.data[0].id,
chatData: response.data,
loading_image: false
});
console.log(this.state.chatData);
alert(this.state.chatData1);
})
.catch(error => {
console.log(error);
});
});
// end axios api call
this.setState((prevState) => ({
activeIds: prevState.activeIds.find((user) => user === id)
? prevState.activeIds
: [...prevState.activeIds, id]
}));
}
close = id => {
this.setState((prevState) => ({
activeIds: prevState.activeIds.filter((user) => user !== id),
}));
};
renderUser = (id) => {
const user = this.state.data.find((user) => user.id === id);
if (!user) {
return null;
}
return (
<OpenedUser key={user.id} data={user} close={this.close}/>
)
}
renderActiveUser = () => {
return (
<div style={{ position: "fixed", bottom: 0, right: 0 }}>
{this.state.activeIds.map((id) => this.renderUser(id)) }
</div>
);
};
render() {
return (
<div>
{this.state.data.map(person => (
<User key={person.id} data={person} open={this.open} />
))}
{this.state.activeIds.length !== 0 && this.renderActiveUser()}
</div>
);
}
}
The problem is you're making the request in the App component and storing in state but you're trying to access the state in a child component so it will never actually read the data.
To fix this you need to pass in the chat data via prop
<OpenedUser
chatData={this.state.chatData}
key={user.id}
data={user}
close={this.close}
/>
Note: In my runnable example, I've replaced your api endpoint with a mock api promise.
const mockApi = () => {
return new Promise((resolve, reject) => {
const json = [{ id: "1", firstname: "faco", lastname: "facoyo" }];
resolve(json);
});
};
class User extends React.Component {
open = () => this.props.open(this.props.data.id, this.props.data.name);
render() {
return (
<React.Fragment>
<div key={this.props.data.id}>
<button
onClick={() => this.open(this.props.data.id, this.props.data.name)}
>
{this.props.data.name}
</button>
</div>
</React.Fragment>
);
}
}
class OpenedUser extends React.Component {
constructor(props) {
super(props);
this.state = {
hidden: false
};
}
componentDidMount() {} // close component didmount
toggleHidden = () =>
this.setState(prevState => ({ hidden: !prevState.hidden }));
close = () => this.props.close(this.props.data.id);
render() {
return (
<div key={this.props.data.id} style={{ display: "inline-block" }}>
<div className="msg_head">
<button onClick={this.close}>close</button>
<div>user {this.props.data.id}</div>
<div>name {this.props.data.name}</div>
{this.state.hidden ? null : (
<div className="msg_wrap">
<div className="msg_body">Message will appear here</div>
<b>
{" "}
Load Message from Database for each user ({this.state.chatData1}
){" "}
</b>
<ul>
{this.props.chatData.map((pere, i) => (
<li key={i}>
{pere.lastname} - {pere.id}----- {pere.username}
</li>
))}
</ul>
</div>
)}
</div>
</div>
);
}
}
class App extends React.Component {
constructor() {
super();
this.state = {
shown: true,
chatData: [],
activeIds: [],
data: [
{ id: 1, name: "user 1" },
{ id: 2, name: "user 2" },
{ id: 3, name: "user 3" },
{ id: 4, name: "user 4" },
{ id: 5, name: "user 5" }
]
};
}
toggle() {
this.setState({
shown: !this.state.shown
});
}
open = (id, name) => {
alert(id);
alert(name);
//start axios api call
const user_data = {
uid: "id",
uname: "name"
};
// this.setState({ loading_image: true }, () => {
// axios
// .post("http://localhost/apidb_react/search_data.php", { user_data })
// .then(response => {
// this.setState({
// chatData1: response.data[0].id,
// chatData: response.data,
// loading_image: false
// });
// console.log(this.state.chatData);
// alert(this.state.chatData1);
// })
// .catch(error => {
// console.log(error);
// });
// });
this.setState({ loading_image: true }, () => {
mockApi().then(data => {
this.setState({
chatData1: data[0].id,
chatData: data,
loading_image: false
});
});
});
// end axios api call
this.setState(prevState => ({
activeIds: prevState.activeIds.find(user => user === id)
? prevState.activeIds
: [...prevState.activeIds, id]
}));
};
close = id => {
this.setState(prevState => ({
activeIds: prevState.activeIds.filter(user => user !== id)
}));
};
renderUser = id => {
const user = this.state.data.find(user => user.id === id);
if (!user) {
return null;
}
return (
<OpenedUser
chatData={this.state.chatData}
key={user.id}
data={user}
close={this.close}
/>
);
};
renderActiveUser = () => {
return (
<div style={{ position: "fixed", bottom: 0, right: 0 }}>
{this.state.activeIds.map(id => this.renderUser(id))}
</div>
);
};
render() {
return (
<div>
{this.state.data.map(person => (
<User key={person.id} data={person} open={this.open} />
))}
{this.state.activeIds.length !== 0 && this.renderActiveUser()}
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
I see a few missing points in your code namely you are using li without ul which is a kind of invalid markup, then you have mapping for .username which is undefined field according to response which may also throw error.

How to dynamically show/hide a list of items in react

I'm having trouble being able to show/hide certain elements in react. Basically, I have a dynamic list of li's, and within the li, I have an label, when you click on the li I want to hide the label and show an input. Usually with jQuery it's as easy as
$('#element').hide()
$('#element2').show()
I'm not quite understanding how to achieve 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 did see other SO's which tell you to use a variable and then to show/hide by changing the variable, but I'm not sure if that's doable for my need, since I have a dynamic list it's not just a single element I am trying to show or hide.
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>
);
}
};
So the above should work for making items editable. Now it doesn't handle actually editing them or returning them to non-editable state. But this should illustrate how you should be accomplishing this the 'react-way'.
I encourage you to drop jQuery. jQuery is going to make your React code harder to manage and make it harder to embrace the react way. If you need something for ajax requests, there are plenty of smaller libraries that just as well suited (superagent is highly recommended but a quick google can lead you to many other)
Let me know if you have any other question.
To show dynamically show/hide a list of items in react implement 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;

Update select react from another select option

I'm trying to update my city select from the selected state, but the city does not update when I change the state:
Here is the part of my render code:
<div>
<label for="state">state:</label>
<SelectInput items="RO-DF-RS-SP-RJ-MG-PR" onChange={this.handleChange} name="state"/>
</div>
{!!this.state.stt &&
(
<div>
<label for="city">city:</label>
<SelectInput url="/static/json/" filename={this.state.stt} onChange={this.props.onChange} name="city"/>
</div>
)
}
<div>
this.props.onChange is just a handler to get the value of the input to save the data at database
And the code:
handleChange(event){
if(event.target.name == "state"){
this.setState({
stt: event.target.value
});
}
if(this.props.onChange) {
this.props.onChange(event);
}
}
sets the correct state (this.state.stt)
Here is my SelectInput:
class SelectInput extends React.Component{
constructor(props){
super(props);
this.state = {
select: "",
items: [],
filename: this.props.filename
}
this.handleChange = this.handleChange.bind(this)
}
componentDidMount(){
if(this.props.filename){
console.log(this.props.filename);
}
if(this.props.items){
this.setState({
items: this.props.items.split("-")
})
}
else if(this.props.url && this.props.filename){
$.ajax({
type: 'GET',
url: `${this.props.url}${this.props.filename}.json`,
headers: { 'Authorization': "Token " + localStorage.token },
success: (result) => {
this.setState({
items: result.child
})
},
error: function (cb) { console.log(cb) }
});
}
}
handleChange(event){
this.setState({
select: event.target.value
});
if(this.props.onChange) {
this.props.onChange(event)
}
}
render(){
return (
<select name={this.props.name} value={this.state.select} onChange={this.handleChange}>
<option value=""></option>
{this.state.items && this.state.items.map(item =>
<option value={item}>{item}</option>
)}
</select>
)
}
}
export default SelectInput
Any idea to solve my problem?
Since you are setting filename dynamically you need to implement componentWillReceiveProps that will make ajax request to load new file.
componentWillReceiveProps({ filename }) {
if(filename !== this.props.filename) {
this.loadItems(filename)
}
}
loadItems(filename) {
$.ajax({
type: 'GET',
url: `${this.props.url}${filename}.json`,
headers: {
'Authorization': "Token " + localStorage.token
},
success: (result) => {
this.setState({
items: result.child
})
},
error: function(cb) {
console.log(cb)
}
});
}

Resources