Why is my input field not allowing me to edit the content? - html

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 }));
};

Related

Function passing null at first run

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>
}

React JSON is undefined

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>

Object.assign({}, obj) in ReactJs to replace objects of json

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()});
}

Iterate a JSON array by a key value in react-native

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);
})
}
}

Displaying data from json as suggestions under a searchbar in reactjs

I have a component called AutoFill which looks like this,
const AutoFill = (props) => {
console.log('proppppppsss', props)
const results = props.results || []
return (
<ul>
{results.map(({ name, href }) => (
<li key={href}>
<a href={href} target='_blank' rel='noopener noreferrer' key={href}>
{name}
</a>
</li>
))}
</ul>
)
}
The Json File where data gets passed through looks like this,
[
{
"a": {
"apple": {
"name": "apple",
"href": "https://www.apple.com/"
},
"armadillo": {
"name": "armadillo",
"href": "https://www.armadillo.com/"
}
},
"b": {
"box": {
"name": "box",
"href": "https://www.box.com/"
},
"berserk": {
"name": "berserk",
"href": "https://www.berserk.com/"
}
}
}
]
The fetch that gets the data from the json
import fetch from 'isomorphic-fetch'
const FetchAndParseResults = (url) => {
return fetch(url).then(response => {
const parsedJson = response.json()
return parsedJson
})
}
export default FetchAndParseResults
The search that makes use of the autofill
import AutoFill from './autofill'
import PropTypes from 'prop-types'
export default class Searchbar extends React.Component {
constructor (props) {
super(props)
this.state = {
className: Styles.input,
icon: Styles.icon__wrapper,
value: []
}
this.input = React.createRef()
}
openInput = () => {
this.setState({
className: Styles.input__active,
icon: Styles.iconWidth
}, () => {
this.input.focus()
})
this.props.onOpen && this.props.onOpen()
}
closeInput = () => {
this.setState({
className: Styles.input,
icon: Styles.icon__wrapper
})
this.props.onClose && this.props.onClose()
}
handleChange = event => {
let value = event.target.value
this.setState({ value })
this.props.performSearch(value)
}
handleSubmit = event => {
event.preventDefault()
}
render () {
console.log('results', this.props.results)
console.log('state.value', this.state.value)
return (
<div>
<form onSubmit={this.handleSubmit} className={Styles.search}>
<div className={this.state.icon}>
<Icon className={Styles.icon__wrapper} iconName='faSearch' onClick={this.openInput} />
</div>
<Search autoComplete='off' value={this.state.value} onChange={this.handleChange} id='search' tabIndex='0' myref={input => { this.input = input }} className={this.state.className} onBlur={this.closeInput} placeholder='Search' />
</form>
<div>
<AutoFill results={this.props.results} />
</div>
</div>
)
}
}
Search.propTypes = {
performSearch: PropTypes.func,
results: PropTypes.array
}
the searchContainer that makes use of everything
import React from 'react'
import Searchbar from './index.js'
import FetchAndParseResults from './FetchAndParseResults.js'
class SearchContainer extends React.Component {
state = {
results: []
}
performSearch = event => {
return FetchAndParseResults('static/autofill.json').then(data => {
this.setState({ results: data })
})
}
render () {
return (
<Searchbar
performSearch={this.performSearch}
results={this.state.results}
/>
)
}
}
export default SearchContainer
At <a href={href} target='_blank' rel='noopener noreferrer' key={href}>{name}</a>
the data of the names should be displayed but instead of the names i get this,
https://gyazo.com/647176b09afcd55b4238f7975c0e7488
An empty unordered list.
Therefore help would be highly appreciated,
and looked into.