i have a little problem with passing data into a JSON file. I have a function that runs onClick. The first run returned:
{
"title": "",
"description": "",
"price": "",
"id": 1
}
but all next runs returns data correctly:
{
"title": "Example title",
"description": "Example description",
"price": "$7",
"id": 2
}
Anyone know how to fix it?
My react code:
const [title, setTitle] = useState('');
const [description, setDescription] = useState('');
const [price, setPrice] = useState('');
const addToCart = (e) => {
e.preventDefault();
setTitle('Example title');
setDescription('Example description');
setPrice('$' + Math.floor(Math.random() * 10 + 1));
const product = { title, description, price};
fetch('http://localhost:8000/basket', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(product)
})
.catch((err) => {
console.log(err.message);
})
}
Because setState is async and only update when component re-render. So you can declare variable to use in post and in setState.
const addToCart = (e) => {
e.preventDefault();
const product = {
title: "Example title",
description: "Example description",
price: "$" + Math.floor(Math.random() * 10 + 1),
};
setTitle(product.title);
setDescription(product.description);
setPrice(product.price);
fetch("http://localhost:8000/basket", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(product),
}).catch((err) => {
console.log(err.message);
});
};
It's likely breaking because you're trying to set state while making a fetch call, on initial empty state values. The design here is wrong, you shouldn't be assigning hard coded state while making a fetch call.
const Form = () => {
const [value, setValue] = useState('')
const submit = () => {
// make fetch call here using value
}
return <form onSubmit={(e) => {e.preventDefault(); submit()}}>
<input type='text' value={value} onChange={(e) => setValue(e.target.value)}
</form>
}
Related
I'm fetching this JSON from an API:
{
"data": {
"email": "test#tre.com",
"inserted_at": "2021-03-30T15:37:06",
"links": [
{
"id": 1,
"title": "My link title",
"url": "http://google.com"
},
{
"id": 2,
"title": "My Youube title",
"url": "http://youtube.com"
}
]
}
}
I'm fetching it this way using Hooks:
export default function Notes() {
const [json, setJSON] = useState([]);
useEffect(() => {
fetch("http://localhost:4000/api/users/1", {
method: "GET"
})
.then((response) => response.json())
.then((json) => {
// console.log(data);
setJSON(json);
})
.catch((err) => {
console.error(err);
});
}, [setJSON]);
Then I try to show it like this:
return (
<>
<div className="content">
{JSON.stringify(json)}
<h1>{json.email}</h1>
</div>
</>
);
The line {JSON.stringify(json)} shows the JSON.
But the line <h1>{json.email}</h1> doesn't show anything.
I don't know why that happens and how can I access my variables.
Thanks . I appreciate any help
Is the data in the form of an array or an object?
You defined the initial state as and array ad hence you cannot do
// you can't do json.email if you expect the response as and array
const [json, setJSON] = useState([]);
change it to
const [json, setJSON] = useState({});
if it is an object. Then in the template do
{json.data && <h1>{json.data.email}</h1>}
<h1>{json.data && json.data.email}</h1>
instead of
<h1>{json.email}</h1>
I have a user details page in Reactjs where I'm fetching the user details and populating it to the corresponding fields. But I'm not able to access key values from the user object.
My sample code is
function EditProfile(props) {
const [user, setUser] = useState()
useEffect(() => {
const fetchUserInfo = async () => {
const profileConfig = {
method: 'GET',
headers: {
'Authorization': 'Bearer ' + auth.token
}
};
fetch(`http://localhost:4000/api/v1/user/me`, profileConfig)
.then(response => response.json())
.then(response => {
console.log("response: ", response.user);
if (response.success === true) {
setUser(response.user)
} else {
alert(response.message)
}
},
(error) => {
alert('User fetching faied: ' + error)
})
}
fetchUserInfo()
}, [])
return (
<div>{user.name}</div>
)
}
The response from the server (user object is)
{
"status": true,
"_id": "5ecfdc403165f709b49a4a0e",
"name": "Anand OL",
"gender": "male",
"dob": "2020-12-13T00:00:00.000Z",
"email": "anand#gmail.com",
"phone": "1234567890",
"createdAt": "2020-05-28T15:44:00.700Z",
"updatedAt": "2020-06-01T08:38:37.902Z",
"__v": 136,
"image": "5ecfdc403165f709b49a4a0e_Image.png"
}
when I try to access name from the user object like user.name
I'm getting an error user is not defined
You need to provide some initial state to display (or conditionally render) while the fetch is occuring.
const [user, setUser] = useState(); // <-- user is undefined!!
Conditionally render UI
return <div>{user && user.name}</div>;
or
return user ? <div>{user.name}</div> : null;
Note: Use caution with the former as not all falsey values are created equal, i.e. Consider return <div>{value && value.property}</div>, if/when value = 0 a falsey value, then a "0" will actually be rendered.
Or you can provide some default state
const [user, setUser] = useState({ name: '' });
I have JSON called by fetch request that looks like this:
[{
"nameSecond": "",
"Id": "",
"First": {
"nameFirst": "",
"Id": ""
}
},
{
"nameSecond": "",
"Id": "",
"First": {
"nameFirst": "",
"Id": ""
}
},
{
"nameSecond": "",
"Id": "",
"First": {
"nameFirst": "",
"Id": ""
}
},
{
"nameSecond": "",
"Id": "",
"First": {
"nameFirst": "",
"Id": ""
}
}
]
I want to replace an object of another JSON to every object of this JSON.
The second JSON which is going to be added to first JSON looks like this:
[{
"nameFirst": "",
"id": ""
},
{
"nameFirst": "",
"id": ""
},
{
"nameFirst": "",
"id": ""
},
{
"nameFirst": "",
"id": ""
}]
What I did is that when ChangeObjectFirst was run ,the object is clicked will be replace by the object Firstof firstJSON and new data will be shown.
<div onClick={((e) => this.ChangeObjectFirst(e, i))}>Change</div>
I used Object.assign({}, itemToReplace) to replace objects but
The main problem is that it will be done just for the first time. For the second time or more clicked object will not be replaced by object First and there will be this TypeError: el is undefined
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
data: [],
dataNew: [],
library: null,
libraryNew: null,
}
}
componentDidMount() {
fetch('/json.bc', {
method: 'POST',
})
.then(response => response.text())
.then(text => {
const Maindata = JSON.parse(text.replace(/\'/g, '"'))
this.setState(state => ({
...state,
data: Maindata
}), () => {
this.reorganiseLibrary()
})
}).catch(error => console.error(error))
fetch('/json2.bc', {
method: 'POST',
})
.then(response => response.text())
.then(text => {
const Maindata = JSON.parse(text.replace(/\'/g, '"'))
this.setState(state => ({
...state,
dataNew: Maindata
}), () => {
this.reorganiseLibraryNew()
})
}).catch(error => console.error(error))
}
reorganiseLibrary = () => {
const { data } = this.state;
let library = data;
library = _.chunk(library);
this.setState({ library })
}
reorganiseLibraryNew = () => {
const { dataNew } = this.state;
let libraryNew = dataNew
libraryNew = _.chunk(libraryNew);
this.setState({libraryNew})
}
renderLibrary = () => {
const { library } = this.state;
if (!library || (library && library.length === 0)) {
return ''
}
return library.map((item, i) => (
<div>
{item.First.nameFirst}
{item.nameSecond}
</div>
))
}
renderLibraryNew = () => {
const { libraryNew } = this.state;
if (!libraryNew || (libraryNew && libraryNew.length === 0)) {
return ''
}
return libraryNew.map((item, i) => (
<div>
{item.nameFirst}
<div onClick={((e) => this.ChangeObjectFirst(e, i))}>Change</div>
</div>
))
}
render() {
const { library, libraryNew } = this.state;
return (
<div>
{this.renderLibrary()}
{this.renderLibraryNew()}
</div>
)
}
ChangeObjectFirst = (e, i) => {
const itemToReplace = this.state.libraryNew[i];
let { data } = this.state;
data = data.map(el => {
el['First'] = Object.assign({}, itemToReplace);
});
this.setState({ data: data });
}
}
ReactDOM.render(<App />, document.getElementById('Result'))
The issue is that while updating, you haven't returned the new data from map. Also since you are using library variables for rendering, you need to call reorganiseLibrary after updating data. A better implementation without mutation would be as below
ChangeObjectFirst = (e, i) => {
const itemToReplace = this.state.libraryNew[i];
let { data } = this.state;
data = data.map((el, idx) => {
return Object.assign({}, el, { First: itemToReplace});
});
this.setState({ data: data }, ()=> {this.reorganiseLibrary()});
}
I would like to display the number of tasks elements in JSON, but I do not know how to go about it.
I want to make something like this:
Tasks to do 2/12 (where 2 - tasks with flag 1, 12 - all tasks)
I tried using the lenght function, but I got the information function lenght is not defined, similarly with the slice function.
[
{
"id":1,
"clients_id":1,
"products_id":1,
"tasks_id":1,
"project_name":"Some project",
"created_at":null,
"updated_at":null,
"clients":{
"id":1,
"client_name":"Some client",
"contact_name":"Some client",
"client_phone":"123123123",
"client_mail":"clientmail#mailclient.com",
"client_nip":"1112223333",
"client_logo":"logo.jpg",
"updated_at":"2019-04-11 09:45:11",
"created_at":"-0001-11-30 00:00:00"
},
"products":{
"id":1,
"product_name":"Some product",
"product_description":"Really nice product bro",
"product_price":"999$",
"updated_at":"2019-04-08 14:35:13",
"created_at":null
},
"tasks":[
{
"id":1,
"project_id":1,
"task_name":"First task",
"task_description":"its very hard task",
"task_due":"2099-01-12 00:00:00",
"status":0,
"created_at":null,
"updated_at":"2019-04-11 14:09:08"
},
{
"id":2,
"project_id":1,
"task_name":"fix task 1",
"task_description":"or something else",
"task_due":"2201-01-12 00:00:00",
"status":1,
"created_at":null,
"updated_at":"2019-04-11 14:10:11"
}
]
}]
<script>
export default {
mounted() {
let app = this;
let id = app.$route.params.id;
app.id = id;
axios.get('/api/v1/projects/' + id)
.then(function (resp) {
app.project = resp.data;
})
.catch(function () {
alert("Could not load your projects")
});
},
data: function () {
return {
//client_id: null,
project: {
id: '',
clients_id: '',
products_id: '',
tasks_id: '',
project_name: '',
updated_at: '',
created_at: '',
clients: ''
},
task: {
status: ''
}
//client: []
}
},
methods: {
saveForm() {
var app = this;
var newproject = app.project;
axios.patch('/api/v1/projects/' + app.id, newproject)
.then(function (resp) {
app.$router.replace('/c/');
})
.catch(function (resp) {
console.log(resp);
alert("Could not create your company");
});
},
taskDone(taskid, projectid){
var app = this;
{{app}};
var newtask = app.task;
var flag = 1;
axios.patch('/api/v1/tasks/' + taskid + '?status='+flag)
.then(function (resp) {
app.$router.push('/pr/view/' + projectid);
location.reload();
})
.catch(function (resp) {
console.log(resp);
alert("Could not create your company");
});
},
taskUnDone(taskid, projectid){
var app = this;
{{app}};
var newtask = app.task;
var flag = 0;
axios.patch('/api/v1/tasks/' + taskid + '?status='+flag)
.then(function (resp) {
app.$router.push('/pr/view/' + projectid);
location.reload();
})
.catch(function (resp) {
console.log(resp);
alert("Could not create your company");
});
}
}
}
</script>
You could create a computed function that returns the length of tasks filtered by status of 1.
computed() {
status() {
const tasks = this.project.tasks;
const complete = tasks.filter(task => task.status === 1);
return `${complete.length}/${tasks.length}`;
}
}
Then use status as a "variable" in your markup.
<p>Tasks done: {{ status }}</p>
Is there anyway to get a value in an object from a json array. I need to get a value from an object based on another value.
I have my code like:
export default class StandardComp extends Component {
constructor(props) {
super(props)
this.state = {
id: '',
email: 'abc#gmail.com',
dataSource: []
};
}
componentDidMount(){
fetch(someURL, {
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
})
.then((response) => response.json())
.then((responseJson) => {
this.setState({dataSource: responseJson})
//dunno what to do here
})
.catch((error) => {
console.error(error);
})
}
}
My "responseJson" is something like this. Then providing the key value (abc#gmail.com), how could I get the string "abcdef"?
[
{
"id": "qwerty",
"email": "cat#gmail.com",
"name": "cat"
},
{
"id": "abcdef",
"email": "abc#gmail.com",
"name": "abc"
}
{
"id": "owowao",
"email": "dog#gmail.com",
"name": "dog"
},
]
Thank you in advance.
Find the element that matches email and return the id.
array::find
const data = [
{
"id": "qwerty",
"email": "cat#gmail.com",
"name": "cat"
},
{
"id": "abcdef",
"email": "abc#gmail.com",
"name": "abc"
},
{
"id": "owowao",
"email": "dog#gmail.com",
"name": "dog"
},
];
const findIdByEmail = (data, email) => {
const el = data.find(el => el.email === email); // Possibly returns `undefined`
return el && el.id; // so check result is truthy and extract `id`
}
console.log(findIdByEmail(data, 'cat#gmail.com'));
console.log(findIdByEmail(data, 'abc#gmail.com'));
console.log(findIdByEmail(data, 'gibberish'));
The code will depend on how you get the value abc#gmail.com.
You'll probably need to pass it in as an argument to componentDidMount via a prop? Or extract it to a separate function. It just depends.
Something like this is the most basic way I'd say.
const value = responseJson.filter(obj => obj.email === 'abc#gmail.com')[0].id
Here it is implemented in your class.
export default class StandardComp extends Component {
...
componentDidMount(){
fetch(someURL, {
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
})
.then((response) => response.json())
.then((responseJson) => {
this.setState({ dataSource: responseJson })
const { email } = this.state
const value = responseJson.filter(obj => obj.email === email)[0].id
})
.catch((error) => {
console.error(error);
})
}
}