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()});
}
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 cannot change the value of this input field in the browser.
<div>
cart.products.map((item) => (
<div className="" key={item.product._id}>
<div
className={`${styles.quantity} col-6 d-flex justify-content-around align-items-center col-md-2
d-md-block mb-2 mb-md-0`}>
<input
className="form-control-sm text-center mb-2"
type="number"
name="quantity"
value={item.quantity}
onChange={(event) => handleChange(event.target)}
/>
</div>
</div>
)
</div>;
The cart data looks like this and is being pulled from redux;
{
"_id": {
"$oid": "5f15ee2c0b94bf240470d70d"
},
"user": {
"$oid": "5f15ee2c0b94bf240470d70c"
},
"products": [
{
"quantity": 2,
"_id": {
"$oid": "5f47d8f2a0c7f4238cb82bf6"
},
"product": {
"$oid": "5f1864917c213e0f5779ee48"
}
},
}
handleChange:
const handleChange = (event.target) => {
const { name, value } = event.target;
setQuantity(value);
};
Make a deep copy of the cart from the reducer thereby giving the component its own copy of the cart;
useEffect(() => {
getCart(cartIn);
}, [cartIn]);
const [cart, setCart] = useState({});
const getCart = (cart) => {
setCart(JSON.parse(JSON.stringify(cart)));
};
Reducer code:
export const CartReducer = (state = initialState, { type, payload }) => {
switch (type) {
case ReducerTypes.SET_CART:
console.log("cart", payload);
const subtotal = computeSubtotal(payload);
addCartToLocalStorage(payload, subtotal);
return {
...state,
cart: payload,
subtotal: subtotal,
numberOfItems: payload.products.length,
};
}
};
Destructuring example using event.target:
const handleChange = (event) => {
const { name, value } = event.target;
setUserData((prevState) => ({ ...prevState, [name]: value }));
};
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);
})
}
}
Like this for example:
<FlatList data={ this.state.foods, this.state.trees }
renderItem={({item}) => <View><Text>{item.food}</Text><Text>{item.tree}</Text></View>
/>
As long as I have the same key (id), is it possible this can work like this?
this.state.foods:
[{
"id": "1",
"food":"chicken",
"cal":"1000",
}]
this.state.trees:
[{
"id": "1",
"tree":"pine",
"size":"10",
}]
EDIT:
render(){
const {trees, foods} = this.state
const combinedArray = trees.map(tree => Object.assign(tree, foods.find(food => food.id == tree.id)));
return(
componentDidUpdate(prevProps, prevState) {
if (!prevState.foods) {
fetch('https://www.example.com/React/food.php')
.then((response) => response.json())
.then((responseJson) => {
this.setState({
isLoading: false,
foods: responseJson.map(item => ({ ...item, progress: new Animated.Value(0), unprogress: new Animated.Value(1) }))
}, function() {
});
})
.catch((error) => {
//console.error(error);
});
fetch('https://www.example.com/React/tree.php')
.then((response) => response.json())
.then((responseJson) => {
this.setState({
isLoading: false,
trees: responseJson
}, function() {
});
})
.catch((error) => {
//console.error(error);
});
}
}
You need to supply a single array to a Flatlist data.
You can group the objects based on id and use them
const {trees, foods} = this.state
const combinedArray = trees.map(tree => Object.assign(tree, foods.find(food => food.id == tree.id)));
and then use combinedArray in the Flatlist
If your state is undefined or null initially then you need to add
constructor(props) {
super(props)
this.state = {
trees: [],
foods: []
}
}
to your class component.
I'm triyng to get data from json file by a id, by I'm getting all the content.
Here the JSON:
[
{ "id": "1", "name": "Carlos", "apellidos":"López", "edad":"30", "ciudad":"Hospitalet" },
{ "id": "2", "name": "Arantxa", "apellidos":"Pavia", "edad":"24", "ciudad":"Barcelona" },
{ "id": "3", "name": "Didac" , "apellidos":"Pedra", "edad":"muchos", "ciudad":"Cornellà" },
{ "id": "4", "name": "Daniel" , "apellidos":"Farnos", "edad":"nolose", "ciudad":"Barcelona" }
]
Service:
private usersUrl = 'app/users.json';
getUser(id: String): Observable<User>{
let body = JSON.stringify(
{
"token": "test",
"content": {
"id": id
}
}
);
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({
headers: headers,
body : body
});
return this.http.get(this.usersUrl, options)
.map(res => res.json()).catch(this.handleError);
}
Angular Component:
ngOnInit(){
this.route.params.subscribe(params => {
let id = +params['id'];
this.apiService.getUser(id).subscribe( (res) => { console.log(res); } );
})
}
Console.log:
Array[4]0: Object1: Object2: Object3: Objectlength: 4__proto__: Array[0]
Is the JSON bad?
Thanks.
Because you didn't filter the result by id.
.map(res => res.json())
.map(x > x.find(x => x.id == id) // filter by selected id
.catch(this.handleError);