handling multiple input in a array of objects - reactjs

I am trying to handle multiple inputs in a array of objects and each object I am mapping to the input field in a form .Now I am getting empty array I want to know where I am doing wrong .I am also sending post axios request and the value I am getting in input text fields through urlParmas using hooks.
import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";
import { useLocation } from "react-router-dom";
import axios from "axios";
import { Button, TextField } from "#material-ui/core";
const MyComponent = () => {
const [sale, setSale] = useState("");
const [district, setDistrict] = useState("");
const obj = [
{
key: 1,
label: "Sales office",
handleChange: (e) => {
setSale(e.target.value);
},
val: sale,
},
{
key: 2,
label: "Sales district",
handleChange: (e) => {
setDistrict(e.target.value);
},
val: sale,
},
];
const [object, setObject] = useState(obj);
const handleSubmit = () => {
axios
.post("localhots:8000", {
sale,
district,
})
.then(() => {});
setSale("");
setDistrict("");
};
const handleComment = (e, item) => {
e.preventDefault();
let result = object;
result = result.map((el) => {
if (el.name === item.name) el.name = e.target.value;
return el;
});
console.log(result);
setObject(result);
};
const { search } = useLocation();
const urlParams = Object.fromEntries([...new URLSearchParams(search)]);
useEffect(() => {
const { salesoff } = urlParams;
setSale(salesoff);
}, []);
object.map((item, index) => {
return (
<div>
<form
onSubmit={(e) => {
e.target.reset();
}}
>
<TextField
name={item.name}
value={item.sale}
label={item.label}
onChange={handleChange}
/>
<Button
type="submit"
fullWidth
variant="contained"
color="primary"
onClick={() => handleSubmit()}
>
Submit
</Button>
</form>
</div>
);
});
};
export default MyComponent;

Related

Notification.requestPermission() is not a function

I am making a website in which I am able to send notifications to all the users but there is a problem, it says
Notification.requestPermission() is not a function
Here is my code:
import React, { useState } from "react";
const Notification = () => {
const [input, setInput] = useState("");
const handleInput = (e) => {
e.preventDefault();
setInput(e.target.value);
};
const sendNotification = () => {
Notification.requestPermission().then((perm) => {
if (perm === "granted") {
new Notification(input, {
body: "Go check it out!",
});
}
});
};
return (
<>
<input type="text" value={input} onChange={handleInput} />
<button onClick={sendNotification}>Send</button>
</>
);
};
export default Notification;
I am using react
Thank You in advance!

How to show the old contents after clearing the search

After showing the content for searched item, while removing the letters from search bar not showing the contents correctly. How to show the contents based on the word which is there in search bar. I have started to learn redux. So need some suggestions
import logo from "./logo.svg";
import "./App.css";
import React, { useState } from "react";
import { useSelector, useDispatch } from "react-redux";
function App() {
const [name, setName] = useState("");
const [searchTerm, setSearchterm] = useState("");
const dispatch = useDispatch();
const data = useSelector((state) => state.add);
console.log(data, "dfata");
const handleChange = (e) => {
setName(e.target.value);
};
console.log(name);
if (data.length == 0) {
return <p>No data</p>;
}
const Submithandler = () => {
dispatch({ type: "ADD_ITEM", name });
setName("");
};
const handleSearch = (e) => {
setSearchterm(e.target.value);
};
const submitSerach = () => {
dispatch({ type: "SEARCH_ITEM", searchTerm });
};
const reset = () => {
dispatch({ type: "RESET", searchTerm });
};
return (
<div className="App">
{data.loading && <p>loading</p>}
<input value={searchTerm} onChange={(e) => handleSearch(e)} />
<button onClick={() => submitSerach()}>search</button>
<button onClick={() => reset()}>reset</button>
<input value={name} onChange={handleChange} />
<button onClick={Submithandler}>Add</button>
{data.item.length === 0 && <p>no item</p>}
{data.item.map((dta, i) => {
return (
<div>
{dta}
<button
onClick={() => dispatch({ type: "REMOVE_ITEM", name: dta })}
>
Remove
</button>
</div>
);
})}
</div>
);
}
export default App;
const INITIAL_STATE = {
item: [],
loading: false,
};
function addReducer(state = INITIAL_STATE, action) {
switch (action.type) {
case "ADD_ITEM":
console.log(action, "ahghsgda");
return { item: [...state.item, action.name] };
case "REMOVE_ITEM":
console.log(action, "REMOPVE");
return {
item: state.item.filter((inditem) => inditem !== action.name),
};
case "SEARCH_ITEM":
console.log(action, "ahghsgda");
const data = [...state.item];
return {
loading: true,
item: [data.filter((product) => product.includes(action.searchTerm))],
};
case "RESET":
return {
item: [...state.item],
};
default:
return state;
}
}
export default addReducer;
After showing the content for searched item, while removing the letters from search bar not showing the contents correctly

React Query: InvalidateQuery not working to update users list

I have a simple app that has a form and list. Currently, I am using query client.InvalidateQueries to update the users' list after submitting the form. As the documentation says, using InvalidateQuery will trigger refetching, but somehow I had not seen an update to the list after adding users. Am I missing something?
Add User
import React, { useState } from 'react';
import { useFormik } from 'formik';
import Input from '../../elements/Input/Input';
import * as Yup from 'yup';
import { QueryClient, useMutation } from 'react-query';
import axios from 'axios';
const queryClient = new QueryClient();
const CreateItemView = () => {
function gen4() {
return Math.random().toString(16).slice(-4);
}
function generateID(prefix) {
return (prefix || '').concat([gen4(), gen4(), gen4(), gen4(), gen4(), gen4(), gen4(), gen4()].join(''));
}
const mutation = useMutation(
(formData) => {
axios.post('http://localhost:8000/users', formData).then((response) => console.log(response));
},
{
onSuccess: () => {
queryClient.invalidateQueries('users');
},
},
);
const [data, setData] = useState([]);
const initialValues = {
id: '',
name: '',
email: '',
channel: '',
};
const onSubmit = (values, { resetForm }) => {
setData([...data, values]);
const ID = generateID().toString();
values.id = ID;
mutation.mutate(values);
resetForm();
};
const validationSchema = Yup.object({
name: Yup.string().required('Required!'),
email: Yup.string().email('Invalid format').required('Required!'),
channel: Yup.string().required('Required!'),
});
const formik = useFormik({
initialValues,
onSubmit,
validationSchema,
});
return (
<div>
<form onSubmit={formik.handleSubmit}>
<Input type={'text'} name={'name'} id={'name'} label={'Name'} formik={formik} />
<Input type={'email'} name={'email'} id={'email'} label={'Email'} formik={formik} />
<Input type={'text'} name={'channel'} id={'channel'} label={'channel'} formik={formik} />
<button type="submit">Submit</button>
</form>
</div>
);
};
export default CreateItemView;
User's list
import React from 'react';
import ListView from './ListView';
import { useQuery } from 'react-query';
import axios from 'axios';
const getUsers = async () => {
const response = await axios.get('http://localhost:8000/users');
return response.data;
};
const ListContainer = () => {
const { data, isLoading, isFetching } = useQuery('users', getUsers);
console.log('list', data);
return <div>{isFetching ? 'loading...' : <ListView dataSource={data} />}</div>;
};
export default ListContainer;
You have to return the fetch function in the mutation. The onSuccess handler will fire when the promise is resolved.
const mutation = useMutation(
formData => {
return axios.post('http://localhost:8000/users', formData)
.then((response) => console.log(response));
},
{
onSuccess: () => {
queryClient.invalidateQueries('users');
},
},
);
i think the solution for your problem is to replace this :
onSuccess: () => {
queryClient.invalidateQueries('users');
},
By this :
onSettled:() => {
queryClient.invalidateQueries('users');
},
you should use the same instance of queryClient from the root of your app which is accessible via the useQueryClient() hook.
Hence you should be doing const queryClient = useQueryClient() instead of generating new instance with const queryClient = new QueryClient().

How to update an object using axios and json server in a react hooks project

I am using a dialog box in a table to edit a row with axios.patch request. While clicking the edit button the values of that particular row are rendered into the TextFields which are in Dialog box but I'm unable to update the values. can anyone help me with this? Please see the Sandox link for better understanding. Thank you.
Sandbox link: https://codesandbox.io/s/material-demo-forked-gdxl3?file=/demo.js
code:
import React, { useState } from "react";
import {
Button,
Typography,
Dialog,
DialogActions,
DialogContent,
DialogTitle,
Table,
TableCell,
TableBody,
TableRow
} from "#material-ui/core";
import { axios } from "./Axios";
import { ValidatorForm, TextValidator } from "react-material-ui-form-validator";
import UserForm from "./UserForm";
import UserTable from "./Table";
export default function SimpleCard() {
const [users, setUsers] = useState([]);
const [postUser, setPostUser] = useState({
id: "",
name: "",
email: ""
});
// console.log(users)
const getUsers = async () => {
const response = await axios.get("/contacts");
if (response && response.data) {
setUsers(response.data);
}
};
React.useEffect(() => {
getUsers();
}, []);
// dialog
const [open, setOpen] = React.useState(false);
const [fullWidth, setFullWidth] = React.useState(true);
const [maxWidth, setMaxWidth] = React.useState("sm");
const handleClickOpen = () => {
setOpen(true);
};
const [open1, setOpen1] = React.useState(false);
const closeDialogForm = () => {
let userDetails = { ...postUser };
userDetails.id = "";
userDetails.name = "";
userDetails.email = "";
setPostUser(userDetails);
};
const handleClose = () => {
closeDialogForm();
setOpen(false);
};
const handleClose1 = () => {
closeDialogForm();
setOpen1(false);
};
const submitForm = async () => {
const response = await axios.post("/contacts", postUser).catch((error) => {
console.log(error);
});
console.log(response);
if (response) {
getUsers();
}
closeDialogForm();
};
const openEditUserDialog = (id) => {
let userDetails = { ...postUser };
for (let index = 0; index < users.length; index++) {
if (id === users[index].id) {
userDetails.id = users[index].id;
userDetails.name = users[index].name;
userDetails.email = users[index].email;
}
}
console.log(userDetails);
setPostUser(userDetails);
setOpen1(true);
};
const updateUser = async (id) => {
const response = await axios
.put(`/contacts/${id}`, postUser)
.catch((error) => {
console.log(error);
});
// console.log(response)
if (response) {
// setOpen(false);
getUsers();
}
};
const deleteUser = async (id) => {
const response = await axios.delete(`/contacts/${id}`).catch((err) => {
console.log(err);
});
if (response) {
getUsers();
}
};
return (
<div>
<Typography>Users</Typography>
<Button
size="small"
variant="contained"
onClick={handleClickOpen}
style={{ textTransform: "none" }}
>
Add
</Button>
<UserTable
users={users}
openEditUserDialog={openEditUserDialog}
deleteUser={deleteUser}
/>
{/* dialog */}
<Dialog
fullWidth={fullWidth}
maxWidth={maxWidth}
open={open}
// onClose={handleClose}
aria-labelledby="max-width-dialog-title"
>
<DialogTitle id="max-width-dialog-title">Add contact</DialogTitle>
<UserForm
submitForm={submitForm}
handleClose={handleClose}
postUser={postUser}
setPostUser={setPostUser}
/>
</Dialog>
{/* edit dialog */}
<Dialog
fullWidth={fullWidth}
maxWidth={maxWidth}
open={open1}
// onClose={handleClose}
aria-labelledby="edit-user"
>
<DialogTitle id="edit-user">Edit contact</DialogTitle>
<UserForm
submitForm={updateUser}
handleClose={handleClose1}
postUser={postUser}
setPostUser={setPostUser}
/>
</Dialog>
</div>
);
}
backend json data:
{
"contacts": [
{
"id": 1,
"name": "Gowtham",
"email": "gowtham#gmail.com"
},
{
"id": 2,
"name": "King",
"email": "gowthamKing#gmail.com"
},
{
"id": 3,
"name": "Hello",
"email": "gowthamKing123#gmail.com"
}
]
}
I have found the solution. Just replace the updateUser arrow function with below code
const updateUser = async () => {
let updateObject = {...postUser}
const response = await axios.patch(`/contacts/${updateObject.id}`, postUser).catch(error => { console.log(error) })
console.log(response)
if (response) {
// setOpen(false);
getUsers()
}
handleClose1();
}

useMutation update,the cache changed,but UI not change

I useMutation to send message ,but the message list in chat window not change. I found that the cache has changed . Please help , I can't understand.
The useQuery not work . UI have no change :(
But~! When I put them in one js file. it works.... why???
The version I used is #apollo/react-hooks 3.1.1
Parent window.js
import React from 'react';
import { useQuery } from "#apollo/react-hooks";
import { GET_CHAT } from "#/apollo/graphql";
import ChatInput from "#/pages/chat/components/input";
const ChatWindow = (props) => {
const { chatId, closeChat } = props;
const { data, loading, error } = useQuery(GET_CHAT, { variables: { chatId: chatId } });
if (loading) return <p>Loading...</p>;
if (error) return <p>{error.message}</p>;
const { chat } = data;
return (
<div className="chatWindow" key={'chatWindow' + chatId}>
<div className="header">
<span>{chat.users[1].username}</span>
<button className="close" onClick={() => closeChat(chatId)}>X</button>
</div>
<div className="messages">
{chat.messages.map((message, j) =>
<div key={'message' + message.id} className={'message ' + (message.user.id > 1 ? 'left' : 'right')}>
{message.text}
</div>
)}
</div>
<div className="input">
<ChatInput chatId={chatId}/>
</div>
</div>
);
};
export default ChatWindow;
Child input.js
import React, { useState } from 'react';
import { useApolloClient, useMutation } from "#apollo/react-hooks";
import { ADD_MESSAGE, GET_CHAT } from "#/apollo/graphql";
const ChatInput = (props) => {
const [textInput, setTextInput] = useState('');
const client = useApolloClient();
const { chatId } = props;
const [addMessage] = useMutation(ADD_MESSAGE, {
update(cache, { data: { addMessage } }) {
const { chat } = client.readQuery({
query: GET_CHAT,
variables: {
chatId: chatId
}
});
chat.messages.push(addMessage);
client.writeQuery({
query: GET_CHAT,
variables: {
chatId: chatId
},
data: {
chat
}
});
}
});
const onChangeInput = (event) => {
event.preventDefault();
setTextInput(event.target.value);
};
const handleKeyPress = (event, chatId, addMessage) => {
if (event.key === 'Enter' && textInput.length) {
addMessage({
variables: {
message: {
text: textInput,
chatId: chatId
}
}
});
setTextInput('');
}
};
return (
<input type="text"
value={textInput}
onChange={(event) => onChangeInput(event)}
onKeyPress={(event) => handleKeyPress(event, chatId, addMessage)}
/>
);
};
export default ChatInput;
You probably solved the issue by now, but for the record:
Your code mutates the chat state:
chat.messages.push(addMessage);
State should not be mutated (see the React setState Docs for more details).
Contruct a new array instead:
const newChat = [...chat, addMessage]

Resources