i want to send message while typing text by using websocket.
but have websocket reference error while typing text.
i think ShareTextComponent onInputEvent function parameter is not exeucte in another location.
so websocket property can't reference in this field
but i don't know how can i fix it.
and i didn't use any state management library such as redux and mobx.
just pure reactjs
[error]
[code]
const ShareTextComponentView = (props) => {
const [isShareMode, setShareMode] = useState(false)
const [syncText, setSyncText] = useState("")
const [isOpen, setOpen] = useState(false)
const [name, setName] = useState("")
let ws = null;
const connect = () => {
ws = new WebSocket(ADDRESS + `/${name}`)
//액세스코드들을 전부 보냄
ws.onopen = () => {
ws.send(JSON.stringify({command: "CONNECT", accessCode: generateAccessCode()}))
console.log(`${ADDRESS}에 접속 되었습니다.`)
setOpen(true)
}
ws.onclose = () => {
ws.send(JSON.stringify({command: "CLOSE"}))
console.log(`${ADDRESS}에 접속 종료 되었습니다.`)
setOpen(false)
}
ws.onmessage = (evt) => {
if (isShareMode) {
return
}
const message = JSON.parse(evt.data)
console.log({message: message})
setSyncText(message.data)
}
ws.onerror = (err) => {
console.log("접속중에 에러가 발생되었습니다.")
console.log(err)
}
}
const close = () => {
if (ws !== null && ws.readyState !== WebSocket.CLOSED) {
ws.close()
}
}
// p2p로 웹소켓으로 연결
useEffect(() => {
if (isOpen) {
return
}
connect()
setOpen(true)
return () => {
//만약 공유모드를 종료했을때 websocket에 shutdown 메세지를 보냄
if (isOpen) {
close()
console.log(`${ADDRESS}에 접속 종료 되었습니다.`)
}
setOpen(false)
}
}, [isShareMode])
const onTextInput = (text) => {
const {name, value} = text.target
if (!isShareMode) {
return
}
console.log("websocket status")
console.log(ws)
console.log("input value")
console.log(value)
if (ws.readyState === WebSocket.CLOSED) {
console.log("Connect Close 되었습니다.")
} else {
ws.send(JSON.stringify({command: "SEND", message: value}))
}
}
const generateAccessCode = () => {
return "hello"
}
const reconnect = () => {
connect()
console.log(ws)
}
return (
<div className="container">
<h1> Please Enter This Area Section</h1>
<h1> {isOpen ? "Connect" : "Disconnect"}</h1>
<div className="name-container">
<label> Name : </label>
<input type="text" onChange={(e) => {
setName(e.target.value)
}}/>
</div>
<button className="reconnect-mode" onClick={reconnect}>Connect</button>
<button className="is-receiever" onClick={() => setShareMode(!isShareMode)}>공유자 입니까?</button>
<h1>{isShareMode ? "공유모드" : "수신모드"}</h1>
<ShareTextComponent accessCode={generateAccessCode()} onInputEvent={onTextInput} syncText={syncText}/>
</div>
)
}
export default ShareTextComponentView;
[after logging in onTextInput]
Add a null check to the top of the function ->
const onTextInput = (text) => {
if (!ws) return;
This will at least help you get past that error and narrow down the rest of the flow.
Related
this is a component that retrieve data from API and generate a table. One button in a column for removing the row opens a Modal.
For avoiding in first component render to trigger api.delete request, an useRef set as false in second useEffect
Modal's Delete button return row info in deleteHandler function which successfully trigger api.delete request on confirmation, remove user in backend however table is not reloading.
Once row is removed expected result is triggering api.get request and display table now updated and without row removed.
In order to get that result I tried with const [reload, setReload] = useState(false); state which introduce another dependency to both userEffect
reload state effectively reload table data updated however it cause also that api.delete request trigger with const ida undefined. Below component script it can find useEffect with my tried.
Any hint or possible solution is appreciated
import React, { Fragment, useEffect, useState, useRef } from "react";
... other imports ...
export default function AllUsers() {
const api = useApi();
const [userData, setUserData] = useState();
const [showModal, setShowModal] = useState(false);
const navigate = useNavigate();
const [modalMessage, setModalMessage] = useState();
const [removeUserId, setRemoveUserId] = useState();
const [ida, setIda] = useState();
let effectRan = useRef(false);
const [reload, setReload] = useState(false);
useEffect(() => {
(async () => {
const response = await api.get("/admin/users");
if (response.ok) {
setUserData(response.body);
} else {
setUserData(null);
}
})();
}, [api]);
useEffect(() => {
if (effectRan.current) {
// console.log("effect run");
(async () => {
const response = await api.delete("/admin/users", {
ida: ida,
});
if (response.ok && response.status === 204) {
console.log(response);
} else {
console.log(response.body.errors);
}
})();
}
return () => (effectRan.current = true);
}, [api, ida]);
const handleEditClick = (e, rowIndex) => {
// console.log("user/" + rowIndex.username);
navigate("/user/" + rowIndex.username, [navigate]);
};
const handleRemoveClick = (e, rowIndex) => {
// console.log([rowIndex]);
setShowModal(true);
setModalMessage({
title: `Remove ${rowIndex.username}`,
message: `User's email to remove ${rowIndex.email}`,
});
setRemoveUserId(rowIndex.id);
};
const closeHandler = () => {
setShowModal(false);
};
const deleteHandler = () => {
// console.log(removeUserId);
setIda(removeUserId);
setShowModal(false);
};
// console.log(ida, idb);
return (
<Fragment>
{showModal && (
<BtModal
show={showModal}
title={modalMessage.title}
message={modalMessage.message}
handleClose={closeHandler}
onConfirm={deleteHandler}
/>
)}
<Body>
<h1>User Table</h1>
{userData === undefined ? (
<Spinner animation="border" />
) : (
<>
{userData === null ? (
<p>Could not retrieve users.</p>
) : userData.length === 0 ? (
<p>There are not users in system</p>
) : (
<UserListTable
newData={userData}
handleEditClick={handleEditClick}
handleRemoveClick={handleRemoveClick}
/>
)}
</>
)}
</Body>
</Fragment>
);
}
useEffect updated with reload state:
useEffect(() => {
(async () => {
const response = await api.get("/admin/users");
if (response.ok) {
setUserData(response.body);
effectRan.current = false;
} else {
setUserData(null);
}
})();
}, [api, reload]);
useEffect(() => {
if (effectRan.current) {
// console.log("effect run");
(async () => {
const response = await api.delete("/admin/users", {
ida: ida,
});
if (response.ok && response.status === 204) {
console.log(response);
setReload(!reload);
} else {
console.log(response.body.errors);
}
})();
}
return () => (effectRan.current = true);
}, [api, ida, reload]);
Here you modify your last edit
const deleteHandler = () => {
// console.log(removeUserId);
setIda(removeUserId);
setReload(!reload)
setShowModal(false);
};
useEffect(() => {
(async () => {
const response = await api.get("/admin/users");
if (response.ok) {
setUserData(response.body);
} else {
setUserData(null);
}
})();
}, [api]);
useEffect(() => {
effectRan.current = reload;
if (effectRan.current) {
// console.log("effect run");
(async () => {
const response = await api.delete("/admin/users", {
ida: ida,
});
if (response.ok && response.status === 204) {
console.log(response);
setReload(!reload);
} else {
console.log(response.body.errors);
}
})();
}
return () => {
effectRan.current = false;
};
}, [api, ida, reload]);
It looks like you're trying to delete an item in the table and confirm it via a prompt. I can see that you've used a lot of useEffects, which might be making things a bit complicated.
Don't worry though, I have a solution that should be much simpler. Let me show you what I mean!
const Page = () => {
const [data, setData] = useState([]);
const [loading, setLoading] = useState([]);
const [deleting, setDeleting] = useState(false);
const [selectedItem, setSelectedItem] = useState(null);
const deleteHandler = async() => {
setDeleting(true);
await api.delete(selectedItem);
// Next you can either update the state itself
let tD = [...data];
const index = tD.findIndex((i) => i.id == selectedItem);
tD.splice(index, 1);
setSelectedItem(tD);
// or refetch data from the backend and update the state
const d = await api.getData();
setData(d);
setDeleting(false);
setSelectedItem(null);
};
useEffect(() => {
const fetchData = async() => {
setLoading(true);
const d = await api.getData();
setData(d);
setLoading(false);
}
fetchData();
}, [])
return loading ? <div>Loading...</div> : <>
{/*Other JSX elements*/}
{selectedItem && <div>
{/*prompt body*/}
<button onClick={() => {setSelectedItem(null)}}>Cancel</button>
<button disabled={deleting} onClick={() => {deleteHandler()}}>Delete</button>
{/*Button will be disabled when the DELETE request is sent*/}
</div>}
{data.map((row) => {
return <tr key={row.id}>
<td>...</td>
<td>...</td>
<td>
<button onClick={setSelectedItem(row.id)}>Delete</button>
</td>
</tr>
})}
</>
}
I have the following React component:
const AuthInit: FC<WithChildren> = ({children}) => {
const {auth, logout, setCurrentUser} = useAuth()
const didRequest = useRef(false)
const [showSplashScreen, setShowSplashScreen] = useState(true)
// We should request user by authToken (IN OUR EXAMPLE IT'S API_TOKEN) before rendering the application
useEffect(() => {
const requestUser = async (apiToken: string) => {
try {
if (!didRequest.current) {
const {data} = await getUserByToken(apiToken)
if (data) {
setCurrentUser(data)
}
}
} catch (error) {
console.error(error)
if (!didRequest.current) {
logout()
}
} finally {
setShowSplashScreen(false)
}
return () => (didRequest.current = true)
}
if (auth && auth.api_token) {
requestUser(auth.api_token)
} else {
logout()
setShowSplashScreen(false)
}
// eslint-disable-next-line
}, [])
return showSplashScreen ? <LayoutSplashScreen /> : <>{children}</>
}
The component contains this line of code:
return () => (didRequest.current = true)
How can I deconstruct this line into multiple lines so that I can put a breakpoint on didRequest.current = true?
function updateDidRequest = () => {
didRequest.current = true;
}
return updateDidRequest;
I have a task to
Implement the functionality of sending a user's email to the server when they click on the "Subscribe" button. To do this, make a POST Ajax request using the /subscribe endpoint.
Implement the functionality of unsubscribing the user's email from
the community list when they click on the "Unsubscribe" button. To do
this, make a POST Ajax request using the /unsubscribe endpoint.
Prevent additional requests if the "Subscribe" and "Unsubscribe"
buttons are pressed while requests to the /subscribe and /unsubscribe
endpoints are in progress. Also, disable them (using the disabled
attribute) and style them using opacity: 0.5. using React.Redux library is prohibited.
So,i have did this task,but the problem is that my form is not doing unsubscribe state,it leaves the email unchanged and the button doesnt change its state from unsubscribe to subscribe,but as a result,when an email is valid,it should give the possibility of sending subscribe fetch request to the server and the button text to change in Unsubscribe and the display of the form to be none,but if the email is not valid,then the button should have the Subscribe text,no fetch request possibilities and the input form to have the display block.Besides this,the value to be stored in local storage and when the page refreshes it leaves the form in the state it was,if was subscribed then all the changes for subscribe are actual and if not than vice-versa.
I have did this task using only javascript and it works as follows:
non-valid email:
valid email:
So,the question is,what i am doing wrong? Why only subscribe fetch works and how to fix the form to make the requested result,i'm exhausted,three days i try to answer this question and i dont understand anything.. please help,thanks in advance!
JoinUsSection component with the form :
import { useState, useEffect } from "react"
import { sendSubscribe } from "../scripts/subscribeFetch"
import { validateEmail } from "../scripts/email-validator"
import { unsubscribeUser } from "../scripts/unsubscribeFetch"
const JoinUsSection = props => {
const { placeholder } = props
//Input div functions
let isSubscribedd = localStorage.getItem('Email') //Function for setting display to none if the form is subscribed and display to block
//console.log(validateEmail(isSubscribedd)) //if form is unsubscribed
let validatedEmail = validateEmail(isSubscribedd)
let setDisplay = ''
if (validatedEmail === true) {
setDisplay = 'none'
localStorage.setItem('isSubscribed', 'true')
} else if (validatedEmail === false) {
setDisplay = 'block'
localStorage.setItem('isSubscribed', 'false')
}
//-------------------------------------
//Input type text Functions
const [email, setEmail] = useState(() => {
//reading data from localStorage
const localEmail = localStorage.getItem('Email')
const initialValue = localEmail
if (localStorage.getItem('Email') !== null) {
return initialValue
} else {
return placeholder
}
})
useEffect(() => {
//storing input email in localStorage
const introducedEmail = email
//console.log(introducedEmail)
localStorage.setItem('Email', introducedEmail)
}, [email])
//------------------------------------------------------
//Input type button Functions
const [isDisabled, setDisabled] = useState(false)
const [isSubscribed, setSubscribe] = useState('Subscribe')
let isFetching = false
let isUsed = false
let introducedEmail = email
const submitClickButton = async () => {
subscribeEmail(introducedEmail) //change the button style and set in local storage isSubscribed to true
sendSubscribe(introducedEmail) //send subscribe fetch to the server
// prevent additional requests upon clicking on "Subscribe" and "Unsubscribe".
if (isFetching) return // do nothing if request already made
isFetching = true
disableBtn()
const response = await fetchMock() //eslint-disable-line
isFetching = false
enableBtn()
isUsed = true
if (validateEmail(introducedEmail) == false) {
isUsed = false
}
}
const fetchMock = () => {
return new Promise(resolve => setTimeout(() => resolve('hello'), 2000))
}
const disableBtn = () => {
// button.disabled = true
// button.style.opacity = '0.5'
setDisabled(true);
}
const enableBtn = () => {
// button.disabled= false
// button.style.opacity = '1'
setDisabled(false);
}
const opacityValue = props.disabled ? 0.5 : 1;
const undoClickButton = () => {
unsubscribeEmail()
isUsed = false
}
const changeButtonState = () => {
isUsed ? undoClickButton() : submitClickButton()
}
const subscribe = () => {
// const subscribeBtn = document.getElementById('subscribeButton')
setSubscribe('Unsubscribe')
// document.getElementById('emailForm').style.display = 'none'
localStorage.setItem('isSubscribed', 'true')
console.log(isUsed)
//document.getElementById('submit-info').value = ''
introducedEmail = ''
}
const unsubscribe = () => {
//const subscribeBtn = document.getElementById('subscribeButton')
setSubscribe('Subscribe')
//document.getElementById('emailForm').style.display = 'block'
localStorage.setItem('isSubscribed', 'false')
console.log(isUsed)
}
const subscribeEmail = (email) => {
const isValidEmail = validateEmail(email)
if (isValidEmail === true) {
subscribe()
} else if (isValidEmail === false) {
unsubscribe()
}
}
const unsubscribeEmail = () => {
unsubscribe()
unsubscribeUser()
localStorage.removeItem('Email')
}
//--------------------------------------
return (
<>
<section className='app-section app-section--image-program' id='programContainer'>
<h2 className='program-title'>Join Our Program</h2>
<h3 className='program-subtitle'>Sed do eiusmod tempor incididunt<br />ut labore et dolore magna aliqua</h3>
<form className='submitFieldWrapper' id='form'>
<div
style={{
display: setDisplay
}}>
<input
className='form-input'
id='submit-info'
type='text'
placeholder='Email'
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
</div>
<input
id='subscribeButton'
className='app-section__button submit-btn'
type='button'
value={isSubscribed}
style={{
opacity: opacityValue
}}
onClick={() => changeButtonState()}
disabled={isDisabled} />
</form>
</section>
</>
)
}
export default JoinUsSection
subscribe fetch request,in different folder and file:
import { validateEmail } from './email-validator.js'
export const sendSubscribe = (emailInput) => {
const isValidEmail = validateEmail(emailInput)
if (isValidEmail === true) {
sendData(emailInput)
}
}
export const sendHttpRequest = (method, url, data) => {
return fetch(url, {
method: method,
body: JSON.stringify(data),
headers: data
? {
'Content-Type': 'application/json'
}
: {}
}).then(response => {
if (response.status >= 400) {
return response.json().then(errResData => {
const error = new Error('Something went wrong!')
error.data = errResData
throw error
})
}
return response.json()
})
}
const sendData = (emailInput) => {
sendHttpRequest('POST', '/subscribe', {
email: emailInput
}).then(responseData => {
return responseData
}).catch(err => {
console.log(err, err.data)
window.alert(err.data.error)
})
}
email validator ,in different folder and file:
const VALID_EMAIL_ENDINGS = ['gmail.com', 'outlook.com', 'yandex.ru']
export const validateEmail = (email) => !!VALID_EMAIL_ENDINGS.some(v => email.includes(v))
export { VALID_EMAIL_ENDINGS as validEnding }
unsubscribe fetch request,in different folder and file:
export const unsubscribeUser = () => {
fetch('/unsubscribe', { method: 'POST' }).then(response => { console.log(response.status) })
}
App.js:
import './App.css';
import JoinUsSection from './components/JoinUsSection';
function App() {
return (
<JoinUsSection/>
);
}
export default App;
So,i managed how to do this task,it wasnt easy but i got to the end. I used react hooks and local storage to store the states of the buttons to mentain the values on page refresh and the problem with buttons i solved with hooks too.
The whole component is below:
import { useState, useEffect } from "react"
import { sendSubscribe } from "../scripts/subscribeFetch"
import { validateEmail } from "../scripts/email-validator"
import { unsubscribeUser } from "../scripts/unsubscribeFetch"
const JoinUsSection = props => {
const { placeholder } = props
//Input div functions
//let isSubscribedd = localStorage.getItem('Email') //Function for setting display to none if the form is subscribed and display to block
//console.log(validateEmail(isSubscribedd)) //if form is unsubscribed
// let validatedEmail = validateEmail(isSubscribedd)
// let setDisplay = ''
// if (isSubscribed = 'Unsubscribe') {
// setDisplay = 'none'
// //localStorage.setItem('isSubscribed', 'true')
// } else if (isSubscribed ='Subscribe') {
// setDisplay = 'block'
// //localStorage.setItem('isSubscribed', 'false')
// }
//-------------------------------------
//Input type text Functions
const [email, setEmail] = useState(() => {
//reading data from localStorage
const localEmail = localStorage.getItem('Email')
const initialValue = localEmail
if (localStorage.getItem('Email') !== null) {
return initialValue
} else {
return placeholder
}
})
useEffect(() => {
//storing input email in localStorage
const introducedEmail = email
//console.log(introducedEmail)
localStorage.setItem('Email', introducedEmail)
}, [email])
//------------------------------------------------------
//Input type button Functions
let [isDisabled, setDisabled] = useState(false)
let [isSubscribed, setSubscribe] = useState('Subscribe')
let [status, setStatus] = useState(false);
let [displayMode, setDisplay] = useState('block')
const [opacity, setOpacity] = useState(1);
useEffect(() => {
const buttonState = localStorage.getItem('Button state')
if (buttonState) {
setSubscribe(JSON.parse(buttonState))
}
}, [])
useEffect(() => {
const statusState = localStorage.getItem('isSubmited')
if (statusState) {
setStatus(JSON.parse(statusState))
}
}, [])
useEffect(() => {
const displayMode = localStorage.getItem('displayMode')
if (displayMode) {
setDisplay(JSON.parse(displayMode))
}
}, [])
useEffect(() => {
localStorage.setItem('Button state', JSON.stringify(isSubscribed))
localStorage.setItem('isSubmited', JSON.stringify(status))
localStorage.setItem('displayMode', JSON.stringify(displayMode))
})
// if (isSubscribed === 'Unsubscribe') {
// setDisplay('none')
// //localStorage.setItem('isSubscribed', 'true')
// } else if (isSubscribed === 'Subscribe') {
// setDisplay('block')
// //localStorage.setItem('isSubscribed', 'false')
// }
// let isFetching = false
//let isUsed = false
let introducedEmail = email
const submitClickButton = async () => {
subscribeEmail(introducedEmail) //change the button style and set in local storage isSubscribed to true
sendSubscribe(introducedEmail) //send subscribe fetch to the server
// prevent additional requests upon clicking on "Subscribe" and "Unsubscribe".
if (isDisabled) return // do nothing if request already made
//setDisabled(true)
disableBtn()
const response = await fetchMock() //eslint-disable-line
// isFetching = false
//setDisabled(false)
enableBtn()
setStatus(true)
if (validateEmail(introducedEmail) == false) {
setStatus(false)
}
}
const fetchMock = () => {
return new Promise(resolve => setTimeout(() => resolve('hello'), 2000))
}
const disableBtn = () => {
// button.disabled = true
// button.style.opacity = '0.5'
setOpacity(0.5)
setDisabled(true);
}
const enableBtn = () => {
// button.disabled= false
// button.style.opacity = '1'
setOpacity(1)
setDisabled(false);
}
//let opacityValue =1
//props.disabled ? 0.5 : 1;
const undoClickButton = () => {
unsubscribeEmail()
setStatus(false)
}
const changeButtonState = () => {
status ? undoClickButton() : submitClickButton()
}
const subscribe = () => {
// const subscribeBtn = document.getElementById('subscribeButton')
setSubscribe('Unsubscribe')
// document.getElementById('emailForm').style.display = 'none'
localStorage.setItem('isSubscribed', 'true')
setDisplay('none')
console.log(status)
// setEmail('')
//document.getElementById('submit-info').value = ''
//localStorage.setItem('Email', '')
}
const unsubscribe = () => {
//const subscribeBtn = document.getElementById('subscribeButton')
setSubscribe('Subscribe')
//document.getElementById('emailForm').style.display = 'block'
localStorage.setItem('isSubscribed', 'false')
setDisplay('block')
console.log(status)
}
const subscribeEmail = (email) => {
const isValidEmail = validateEmail(email)
if (isValidEmail === true) {
subscribe()
} else if (isValidEmail === false) {
unsubscribe()
}
}
const unsubscribeEmail = () => {
unsubscribe()
unsubscribeUser()
setEmail('')
localStorage.removeItem('Email')
}
//--------------------------------------
return (
<>
<main id='app-container'>
<section className='app-section app-section--image-program' id='programContainer'>
<h2 className='program-title'>Join Our Program</h2>
<h3 className='program-subtitle'>Sed do eiusmod tempor incididunt<br />ut labore et dolore magna aliqua</h3>
<form className='submitFieldWrapper' id='form'>
<div
className="form-wrapper"
id="emailForm"
style={{
display: displayMode
}}
>
<input
className='form-input'
id='submit-info'
type='text'
placeholder='Email'
value={email}
onChange={(e) => setEmail(e.target.value)}
></input>
</div>
<input
id='subscribeButton'
className='app-section__button submit-btn'
type='button'
value={isSubscribed}
style={{
opacity
}}
onClick={() => { changeButtonState() }}
disabled={isDisabled} ></input>
</form>
</section>
</main>
</>
)
}
export default JoinUsSection
This code is inside a functional component:
the choose (onclick function) keeps printing undefined,
I used const [chosen, setchosen] = useState([])
Here is the full code
Everything is correctly imported
The idea is that I want the owner of the post to be able to pick a candidate that applied to the post
................................................................................................................................................................................................................................................................................................
const Details = () => {
const { key } = useParams();
console.log(key)
const [loading, setLoading] = useState(true);
const [details, setDetails] = useState({});
const [userid, setuserid] = useState([]);
const [sameuser, setSameuser] = useState(false)
const [pressed, setpressed] = useState(false)
const [pressed2, setpressed2] = useState(false)
const [chosen, setchosen] = useState([])
useEffect(() => {
var docRef = db.collection("Quests").doc(key);
docRef.get().then(function (doc) {
if (doc.exists) {
console.log("Document data:", doc.data());
setDetails(doc.data());
setLoading(false)
} else {
// doc.data() will be undefined in this case
console.log("No such document!");
}
}).catch(function (error) {
console.log("Error getting document:", error);
});
}, []);
if (loading) {
return <div className="Quests">Still loading...</div>;
}
auth.onAuthStateChanged((user) => {
if (user) {
setuserid(user.uid)
}
userid == details.ownerId ? (
setSameuser(true)) : (
console.log("not same user")
)
});
let button;
const AddCandidate = e => {
var docRef = db.collection("Quests").doc(key)
let currCandidates = details.candidates;
currCandidates.push(userid)
docRef.set({
candidates: currCandidates
}, { merge: true });
setpressed(true)
}
let candidatelist
const Pickuser = () => {
console.log("hi", details.candidates)
setpressed2(true)
}
const choose = (value) => {
// console.log("hi")
// // // candidatelist = <ol>{details.candidates.map(details => <li>{details}</li>)}</ol>
// // setpressed2(true)
console.log(chosenvalue)
setchosen(chosenvalue)
console.log(chosen)
}
if (sameuser) {
if (pressed2) {
var chosenvalue
button = <Button onClick={Pickuser}>Pick user</Button>
candidatelist = <ol>{details.candidates.map(details => <Button value={chosenvalue} onClick={choose} >{details}</Button>)}</ol>
}
else {
button = <Button onClick={Pickuser}>Pick user</Button>
candidatelist = <h1></h1>
}
} else {
if (pressed) {
button = <h1>Thanks for applying</h1>
console.log("pressed")
candidatelist = <h1></h1>
}
else {
button = <Button onClick={AddCandidate}>Apply</Button>
candidatelist = <h1></h1>
}
}
return (
<div>
<h1>{details.title}</h1>
<h2>{details.detailspara}</h2>
<h3> {details.Category}</h3>
<h3>{details.picofquest}</h3>
<img
src={details.url}
alt="Uploaded Images"
height="300"
width="400"
/>
<h3>${details.price}</h3>
<h3>{details.time}</h3>
<h3>{details.ownerId}</h3>
<h3>{userid}</h3>
{button}
{candidatelist}
</div>
)
}
export default Details;
if function passed to event handler, event object is passed to the function. the simplest way to get value when button is clicked is like following code
<Button
onClick={() => someFunction(value)}
>
Button Text
</Button>
https://reactjs.org/docs/events.html#overview
https://reactjs.org/docs/handling-events.html
const choose = (value) => {
// console.log("hi")
// // // candidatelist = <ol>{details.candidates.map(details => <li>{details}</li>)}</ol>
// // setpressed2(true)
console.log(chosenvalue)
setchosen(chosenvalue)
console.log(chosen)
}
in this choose function prints undefined because, chosenvalue is undefined and this variable hasn't declared choose function's scope.
to fix the problem
if (pressed2) {
button = <Button onClick={Pickuser}>Pick user</Button>
candidatelist = (
<ol>
{details.candidates.map(details =>
// pass appropriate value as parameter what you want to get when the button is clicked. detail or value.
<Button onClick={() => choose(details)}>
{details}
</Button>
)}
</ol>
)
}
...
const choose = (value) => {
console.log(value);
setchosen(value);
}
other way is using current target from passed Synthetic event
const choose = (event) => {
const { currentTarget: { value } } = event;
console.log(value)
setchosen(value)
}
The first argument passed to an event handler is the event object, not a value.
You can use currentTarget to get the button.
Then it's value property will give you the value.
const choose = (event) => {
const button = event.currentTarget;
const value = button.value;
// …
While my code works from the functionalities, I have to click "refresh" after each click to see the changes. For example when I click "Add note" I have to refresh the page in order to see it. While it compiles successfully, the console shows three errors:
import { API, graphqlOperation } from "aws-amplify";
import { withAuthenticator } from "aws-amplify-react";
import React, { useEffect, useState } from "react";
import { createNote, deleteNote, updateNote } from "./graphql/mutations";
import { listNotes } from "./graphql/queries";
import {
onCreateNote,
onDeleteNote,
onUpdateNote
} from "./graphql/subscriptions";
const App = () => {
const [id, setId] = useState("");
const [note, setNote] = useState("");
const [notes, setNotes] = useState([]);
useEffect(() => {
getNotes();
const createNoteListener = API.graphql(
graphqlOperation(onCreateNote)
).subscribe({
next: noteData => {
const newNote = noteData.value.data.onCreateNote;
setNotes(prevNotes => {
const oldNotes = prevNotes.filter(note => note.id !== newNote.id);
const updatedNotes = [...oldNotes, newNote];
return updatedNotes;
});
setNote("");
}
});
const deleteNoteListener = API.graphql(
graphqlOperation(onDeleteNote)
).subscribe({
next: noteData => {
const deletedNote = noteData.value.data.onDeleteNote;
setNotes(prevNotes => {
const updatedNotes = prevNotes.filter(
note => note.id !== deletedNote.id
);
return updatedNotes;
});
}
});
const updateNoteListener = API.graphql(
graphqlOperation(onUpdateNote)
).subscribe({
next: noteData => {
const updatedNote = noteData.value.data.onUpdateNote;
setNotes(prevNotes => {
const index = prevNotes.findIndex(note => note.id === updatedNote.id);
const updatedNotes = [
...prevNotes.slice(0, index),
updatedNote,
...prevNotes.slice(index + 1)
];
return updatedNotes;
});
setNote("");
setId("");
}
});
return () => {
createNoteListener.unsubscribe();
deleteNoteListener.unsubscribe();
updateNoteListener.unsubscribe();
};
}, []);
const getNotes = async () => {
const result = await API.graphql(graphqlOperation(listNotes));
setNotes(result.data.listNotes.items);
};
const handleChangeNote = event => setNote(event.target.value);
const hasExistingNote = () => {
if (id) {
const isNote = notes.findIndex(note => note.id === id) > -1;
return isNote;
}
return false;
};
const handleAddNote = async event => {
event.preventDefault();
// Check if we have an exisiting note. If so, then update it.
if (hasExistingNote()) {
handleUpdateNote();
} else {
const input = { note };
await API.graphql(graphqlOperation(createNote, { input }));
}
};
const handleUpdateNote = async () => {
const input = { id, note };
await API.graphql(graphqlOperation(updateNote, { input }));
};
const handleDeleteNote = async noteId => {
const input = { id: noteId };
await API.graphql(graphqlOperation(deleteNote, { input }));
};
const handleSetNote = ({ note, id }) => {
setNote(note);
setId(id);
};
return (
<div className="flex flex-column items-center justify-center pa3 bg-washed-red">
<h1 className="code f2-l">Amplify Notetake</h1>
{/* Note Form */}
<form onSubmit={handleAddNote} className="mb3">
<input
type="text"
className="pa2 f4"
placeholder="Write your note"
onChange={handleChangeNote}
value={note}
/>
<button className="pa2 f4" type="submit">
{id ? "Update note" : "Add note"}
</button>
</form>
{/* Notes list */}
<div>
{notes.map(item => (
<div key={item.id} className="flex items-center">
<li onClick={() => handleSetNote(item)} className="list pa1 f3">
{item.note}
</li>
<button
onClick={() => handleDeleteNote(item.id)}
className="bg-transparent bn f4"
>
<span>×</span>
</button>
</div>
))}
</div>
</div>
);
};
export default withAuthenticator(App, { includeGreetings: true });
If you are using CLI version 2.0 and above, owner is a required argument. This is explained more in the link below:
https://aws-amplify.github.io/docs/cli-toolchain/graphql#authorizing-subscriptions
After I added Auth in the import
import { API, graphqlOperation, Auth } from 'aws-amplify';
captured the current user and passed it into the subscription it started working for me.
useEffect(() => {
getNotes();
const owner = Auth.user.getUsername();
const createNoteListener = API.graphql(
graphqlOperation(onCreateNote, { owner })
).subscribe({
next: noteData => {
const newNote = noteData.value.data.onCreateNote;
setNotes(prevNotes => {
const oldNotes = prevNotes.filter(note => note.id !== newNote.id);
const updatedNotes = [...oldNotes, newNote];
return updatedNotes;
});
setNote("");
}
});