How can I upload a image file using and react Socket-IO? - reactjs

i want to make a chat app with react and socket.io
i downloaded code from https://github.com/adrianhajdin/project_chat_application.
I want to add upload file function using socketio_file_upload
but when i upload the img. there is nothing happen..
this is my code
index.js (server)
const express = require('express');
const socketio = require('socket.io');
const http = require('http');
const siofu = require("socketio-file-upload");
const { addUser, removeUser, getUser, getUsersInRoom } = require('./users');
const PORT = process.env.PORT || 5000
const router = require('./router')
const app = express()
console.log(app,'------------------app----------')
const server = http.createServer(app)
const io = socketio(server)
io.on('connection', (socket)=>{
const uploader = new siofu();
uploader.dir = "/uploads";
uploader.listen(socket);
uploader.on("saved", function(event){
});
uploader.on("error", function(event){
});
socket.on('join', ({name, room}, callback)=>{
const { user, error } = addUser({ id:socket.id, name, room })
if(error) {
return callback(error)
}
//admin system정보 여기서
socket.emit('message', { user:'admin', text:`${user.name}, welcome to the room ${user.room}` })
//braodcast는 room에 있는 모든 사람에게 msg를 보낸다.
socket.broadcast.to(user.room).emit('message', { user: 'admin', text: `${user.name} has joined!` });
socket.join(user.room)
io.to(user.room).emit('roomData', {room: user.room, users: getUsersInRoom(user.room)})
callback()
})
socket.on('sendMessage', (message, callback) => {
const user = getUser(socket.id);
io.to(user.room).emit('message', { user: user.name, text: message });
io.to(user.room).emit('roomData', { room: user.room, users: getUsersInRoom(user.room)});
callback();
});
socket.on('disconnect', () => {
const user = removeUser(socket.id)
io.to(user.room).emit('message', { user:'admin', text: `${user.name} has left`})
})
})
app.use(siofu.router)
server.listen(PORT, ()=> console.log('---SERVER START---'))
Chat.jsx
import React, { useState, useEffect, useRef } from 'react';
import queryString from 'query-string'
import io from 'socket.io-client'
import './chat.css'
import InfoBar from '../InfoBar/InfoBar'
import Messages from '../Messages/Messages'
import Input from '../Input/Input'
let socket ='default'
const Chat = ({location}) => {
const [name, setName] = useState('');
const [room, setRoom] = useState('');
const [message, setMessage] = useState('')
const [messages, setMessages] = useState([])
const END_POINT = 'localhost:5000'
//componentdidmount와 같다
useEffect(()=>{
const {name, room} = queryString.parse(location.search)
socket = io(END_POINT)
setName(name)
setRoom(room)
//server에 join을 통해서 데이터를 보냄
socket.emit('join', {name, room}, (res)=>{
})
//useEffect()애서 return 은 unmount와 같다. 즉 user leave일 때 사용!
return () =>{
socket.emit('disconnect')
socket.off()
}
},[END_POINT, location.search])
useEffect(() => {
socket.on('message', (message) =>{
setMessages([...messages, message])
})
// uploader.listenOnInput(document.getElementById("siofu_input"));
}, [messages])
const sendMessage = (event) => {
event.preventDefault();
if(message) {
socket.emit('sendMessage', message, () => setMessage(''));
}
}
return (
<div className="outerContainer">
<div className="container">
<InfoBar room={room} />
<Messages messages={messages} name={name} />
<Input socket={socket} message={message} setMessage={setMessage} sendMessage={sendMessage} />
</div>
</div>
);
};
export default Chat;
Input.jsx
import React, { Component } from 'react';
import SocketIOFileUpload from '../../../../server/node_modules/socketio-file-upload'
import './input.css';
class Input extends Component {
uploadFile = (e) => {
const {socket} = this.props
console.log("uploading");
// const files = e.target.files;
const siofu = new SocketIOFileUpload(socket);
siofu.listenOnInput(document.getElementById("siofu_input"));
};
render() {
const { setMessage, sendMessage, message, socket } = this.props
return (
<form className="form">
<input
className="input"
type="text"
placeholder="Type a message..."
value={message}
onChange={({ target: { value } }) => setMessage(value)}
onKeyPress={event => event.key === 'Enter' ? sendMessage(event) : null}
/>
<input type="file" id="siofu_input" onChange={this.uploadFile.bind(this)}/>
<button className="sendButton" onClick={e => sendMessage(e)}>Send</button>
</form>
);
}
}
export default Input;
users.js
const users = [];
const addUser = ({ id, name, room }) => {
name = name.trim().toLowerCase();
room = room.trim().toLowerCase();
const existingUser = users.find((user) => user.room === room && user.name === name);
if(!name || !room) return { error: 'Username and room are required.' };
if(existingUser) return { error: 'Username is taken.' };
const user = { id, name, room };
users.push(user);
return { user };
}
const removeUser = (id) => {
const index = users.findIndex((user) => user.id === id);
if(index !== -1) return users.splice(index, 1)[0];
}
const getUser = (id) => users.find((user) => user.id === id);
const getUsersInRoom = (room) => users.filter((user) => user.room === room);
module.exports = { addUser, removeUser, getUser, getUsersInRoom };
How can i upload img file to chat app....

At first, you must create "uploads" folder to upload files.
When I run the app on local, I created folder on to D drive and changed uploader.dir from '/uploads' to "uploads";
At second, when you select DOM, you used document.elementById, this is wrong, must use ref={(el)=>this.variable=el} and change to siofu.listenOnInput(this.variable);
At third, you did define upload logic in onChange event listener, have to define in componentDidMount().

Related

Uncaught TypeError: Cannot read properties of undefined (reading 'filter')

I am trying to connect frontend and backend. I can't understand why filter() function is undefined. In localhost it worked but when i am trying to put it on web with fly.io it doesn't work anymore. Here's code
import { useState, useEffect } from 'react'
import Person from './components/Person'
import Filter from './components/Filter'
import NewPersonForm from './components/NewPersonForm'
import personService from './services/persons'
import Notification from './components/Notification'
import './index.css'
const App = () => {
const [persons, setPersons] = useState([])
const [newName, setNewName] = useState('')
const [newNumber, setNewNumber] = useState('')
const [newFilter, setNewFilter] = useState('')
const [successMessage, setSuccessMessage] = useState(null)
useEffect(() => {
console.log('effect')
personService
.getAll()
.then(response => {
console.log('fulfilled')
setPersons(response.data)
})
}, [])
const addPerson = (event) => {
event.preventDefault()
const personObject = {
name: newName,
number: newNumber
}
console.log(newName)
const inArray = persons.filter((person) => person.name === newName)
if (inArray.length === 0){
personService
.create(personObject)
.then(response => {
setPersons(persons.concat(response.data))
setSuccessMessage(
`Added ${personObject.name}`
)
setTimeout(() => {
setSuccessMessage(null)
}, 3000)
setNewName('')
setNewNumber('')
})
console.log('button clicked', event.target)
} else{
alert(`${newName} is already in the phonebook`)
}
}
const deletePerson = (person) => {
const persontodelete = person.name
if (window.confirm(`Delete ${persontodelete}?`)){
personService
.remove(person.id)
.then(response => {
setPersons(persons.filter(p => p.id !== person.id))
setSuccessMessage(
`Deleted ${person.name}`
)
setTimeout(() => {
setSuccessMessage(null)
}, 3000)
})
}
}
const filteredPersons = persons.filter(person =>
person.name.toLowerCase().includes(newFilter.toLowerCase()))
const handlePersonChange = (event) => {
console.log(event.target.value)
setNewName(event.target.value)
}
const handleNumberChange = (event) => {
console.log(event.target.value)
setNewNumber(event.target.value)
}
const handleFilterChange = (event) => {
setNewFilter(event.target.value)
}
return (
<div>
<h2>Phonebook</h2>
<Notification message={successMessage} />
<Filter newFilter={newFilter} handleFilterChange={handleFilterChange}/>
<h2>add new</h2>
<NewPersonForm
addPerson={addPerson}
newName={newName}
handlePersonChange={handlePersonChange}
newNumber={newNumber}
handleNumberChange={handleNumberChange}
/>
<h2>Numbers</h2>
<Person filteredPersons={filteredPersons} deletePerson={deletePerson}/>
<div>debug: {newName}</div>
<div>debug: {newNumber}</div>
</div>
)
}
export default App
I am trying to get array with names and numbers from backend. Error disappears if I do following change
useEffect(() => {
console.log('effect')
personService
.getAll()
.then(data => {
console.log('fulfilled')
setPersons(data)
})
}, [])
but new error occures in toLowecase() function.
const filteredPersons = persons.filter(person =>
person.name.toLowerCase().includes(newFilter.toLowerCase()))

ontrack is not firing in webrtc

I am making a video calling application using react , webrtc and firebase. I am able to connect both local and remote connection but i am not receiving the remote mediastream. The ontrack function is not firing and i don't know why.
import logo from './logo.svg';
import { useEffect, useRef } from 'react';
import './App.css';
import { useState } from 'react';
import { initializeApp } from 'firebase/app'
import { addDoc, collection, doc, getDoc, getFirestore, onSnapshot, setDoc, updateDoc } from 'firebase/firestore'
function App() {
const myVideoRef = useRef(null)
const yourVideoRef = useRef(null)
const [cameras, setcameras] = useState()
const [myCallId, setmyCallId] = useState()
const [callId, setcallId] = useState()
const [roomId ,setroomId] = useState()
const servers = {
iceServers: [
{
urls: ['stun:stun1.l.google.com:19302', 'stun:stun2.l.google.com:19302'],
},
],
iceCandidatePoolSize: 10,
}
const pc = new RTCPeerConnection(servers)
const firebaseConfig = {
// my config
}
const app = initializeApp(firebaseConfig)
const db = getFirestore(app)
async function getConnectedDevices(type){
const devices = await navigator.mediaDevices.enumerateDevices()
return devices.filter(device => device.kind === type)
}
async function openCamera(cameraId){
const constraints = {
'audio': {'echoCancellation': true},
'video': {
'deviceId': cameraId,
}
}
navigator.mediaDevices.getUserMedia(constraints)
.then((stream) => {
stream.getTracks().forEach((track) => {
pc.addTrack(track,stream)
})
myVideoRef.current.srcObject = stream
})
// this part is not firing.
let remoteStream = new MediaStream()
pc.ontrack = (event) => {
event.streams[0].getTracks().forEach((track) => {
remoteStream.addTrack(track)
})
}
yourVideoRef.current.srcObject = remoteStream
}
async function call(){
const callDoc = doc(collection(db,"calls"))
const offerCandidates = collection(callDoc,"offerCandidates")
const answerCandidates = collection(callDoc,"answerCandidates")
setmyCallId(callDoc.id)
pc.onicecandidate = (event) => {
console.log(event.candidate)
event.candidate && addDoc(offerCandidates,event.candidate.toJSON())
}
const offerDescription = await pc.createOffer()
await pc.setLocalDescription(offerDescription)
const offer = {
sdp: offerDescription.sdp,
type: offerDescription.type
}
await setDoc(callDoc, { offer } )
onSnapshot(callDoc, snapshot => {
const data = snapshot.data()
if(!pc.currentRemoteDescription && data?.answer){
const answerDescription = new RTCSessionDescription(data.answer)
pc.setRemoteDescription(answerDescription)
}
})
onSnapshot(answerCandidates, snapshot => {
snapshot.docChanges().forEach((change) => {
if(change.type === 'added'){
console.log(change.doc.data())
const candidate = new RTCIceCandidate(change.doc.data())
pc.addIceCandidate(candidate)
console.log(yourVideoRef.current.srcObject)
console.log(myVideoRef.current.srcObject)
}
})
})
}
async function answer(){
const callDoc = doc(collection(db,"calls"),callId)
const offerCandidates = collection(callDoc,"offerCandidates")
const answerCandidates = collection(callDoc,"answerCandidates")
pc.onicecandidate = (event) => {
event.candidate && addDoc(answerCandidates,event.candidate.toJSON())
}
const callData = (await getDoc(callDoc)).data()
console.log(callData)
const offerDescription = callData.offer
await pc.setRemoteDescription(new RTCSessionDescription(offerDescription))
const answerDescription = await pc.createAnswer()
await pc.setLocalDescription(answerDescription)
const answer = {
type: answerDescription.type,
sdp: answerDescription.sdp,
}
await updateDoc(callDoc, {answer})
onSnapshot(offerCandidates, snapshot => {
snapshot.docChanges().forEach((change) => {
console.log(change)
if(change.type === 'added'){
let data = change.doc.data()
pc.addIceCandidate(new RTCIceCandidate(data))
}
})
})
}
useEffect(() => {
async function fetch(){
const cameras = await getConnectedDevices('videoinput')
setcameras(cameras)
}
fetch()
},[])
return (
<div className="App">
<div className='flex flex-row'>
{cameras && cameras.map( camera => <h2 className='m-3' key={camera.deviceId} onClick={() => openCamera(camera.deviceId)} >{camera.label}</h2>)}
</div>
<div className='flex flex-row'>
<video className='w-1/2' ref={myVideoRef} autoPlay />
<video className='w-1/2' ref={yourVideoRef} autoPlay />
</div>
<button onClick={call} className='bg-gray-200'>Call</button>
<div className='flex flex-row'>
<input onChange={(e) => setcallId(e.target.value)} className='border-[4px] border-black' />
<button onClick={answer} className='bg-gray-200'>Answer</button>
</div>
<h2>{myCallId}</h2>
</div>
);
}
export default App;
The ontrack function is not firing. I have put the function in useEffect , on top outside all the functions, before setremotedescription but it is still not firing.
let remoteStream = new MediaStream()
pc.ontrack = (event) => {
event.streams[0].getTracks().forEach((track) => {
remoteStream.addTrack(track)
})
}
yourVideoRef.current.srcObject = remoteStream

How to prevent react is rendering 2 times

I am facing a problem where the react is rendering 2 times but I do not see any problem in the code or it is come from the socket? I noticed this problem when consoling and when displaying data, the data duplicate. Below I put my client react code with the server socket code.
React client
import "./App.css";
import io from "socket.io-client";
import { useEffect, useState } from "react";
const socket = io.connect("http://localhost:3001");
function App() {
const [text, setText] = useState("");
const [room, setRoom] = useState("");
const [data, setData] = useState([]);
const [action, setAction] = useState(true);
console.log("data", data);
console.log(text);
console.log(room);
const sendMessage = () => {
socket.emit("send_message", { text, room });
};
const joinRoom = () => {
if (room !== "") {
socket.emit("join_room", room);
}
};
useEffect(() => {
socket.on("receive_message", (msg) => {
setData((prev) => [
...prev,
{
message: msg,
},
]);
});
}, [action]);
return (
<div className="App">
{data.map((da) => (
<p>{da.message}</p>
))}
<input
type="text"
placeholder="room no"
onChange={(e) => {
setRoom(e.target.value);
}}
></input>
<button onClick={joinRoom}>Join</button>
<br />
<input
type="text"
placeholder="message .."
onChange={(e) => {
setText(e.target.value);
}}
></input>
<button onClick={sendMessage}>Send Message</button>
</div>
);
}
export default App;
Socket server
const express = require("express");
const app = express();
const http = require("http");
const { Server } = require("socket.io");
const cors = require("cors");
app.use(cors());
const server = http.createServer(app);
const io = new Server(server, {
cors: {
origin: "http://localhost:3000",
methods: ["GET", "POST"],
},
});
io.on("connection", (socket) => {
// console.log(`User Connected ${socket.id}`);
socket.on("join_room", (data) =>{
socket.join(data);
})
socket.on("send_message", (data) => {
socket.to(data.room).emit("receive_message", data.text);
})
});
server.listen(3001, () => {
console.log("SERVER OK");
});

React: Best way to pass Firestore info to components?

Can't figure out an efficient way to set a user's profile and then pass that data onwards to other components as needed.
Below is an example of my current logic, and although the app works, the rendering is not efficient. When I click on various parts of my app, the data coming from my UserProfile component is re-rendering every time causing the text to change from the initial text to the rendered data text.
The main issue, I believe, is the communication between the UserProfile and Dashboard Home snippets below. I'm new to the useEffect logic, so I would imagine the inefficient setup is with that hook.
Any help or nudge in the right direction is appreciated!
Thanks
AuthContext file => Setting the current user
import React, { useContext, useState, useEffect } from 'react';
import firebase from 'firebase/app';
import {
auth,
signInWithGoogle,
createUserProfileDocument,
firestore,
} from '../firebase.utils';
const AuthContext = React.createContext();
export const useAuth = () => {
return useContext(AuthContext);
};
export const AuthProvider = ({ children }) => {
const [currentUser, setCurrentUser] = useState();
const [loading, setLoading] = useState(true);
const signup = (email, password) => {
return auth.createUserWithEmailAndPassword(email, password);
};
const login = (email, password) => {
return auth.signInWithEmailAndPassword(email, password);
};
const logout = () => {
setCurrentUser(null);
return auth.signOut();
};
const resetPassword = email => {
return auth.sendPasswordResetEmail(email);
};
const updateEmail = email => {
return currentUser.updateEmail(email);
};
const updatePassword = password => {
return currentUser.updatePassword(password);
};
const deleteProfile = () => {
currentUser.delete();
firestore.doc(`users/${currentUser.uid}`).delete();
};
const updateName = displayName => {
return currentUser.updateProfile({
displayName: displayName,
});
};
const setName = displayName => {
return auth.currentUser.updateProfile({
displayName: displayName,
});
};
const googleSignIn = () => {
const google = signInWithGoogle();
setCurrentUser(google);
return google;
};
const updatePersonalSettings = data => {
createUserProfileDocument(currentUser, data);
};
const updateAccountSettings = data => {
createUserProfileDocument(currentUser, data);
};
console.log(currentUser);
useEffect(() => {
const unsubscribe = auth.onAuthStateChanged(user => {
setCurrentUser(user);
setLoading(false);
});
return unsubscribe;
}, []);
const value = {
currentUser,
login,
signup,
logout,
resetPassword,
updateEmail,
updatePassword,
updateName,
setName,
googleSignIn,
updatePersonalSettings,
updateAccountSettings,
deleteProfile,
};
return (
<AuthContext.Provider value={value}>
{!loading && children}
</AuthContext.Provider>
);
};
UserProfile file => Setting the userInfo
import { useState, useEffect } from 'react';
import { useAuth } from '../context/auth-context';
import { createUserProfileDocument } from '../firebase.utils';
const UserProfile = () => {
const { currentUser } = useAuth();
const [userInfo, setUserInfo] = useState();
const [loading, setLoading] = useState(true);
const setUserData = async () => {
if (currentUser) {
const userRef = await createUserProfileDocument(currentUser);
userRef.onSnapshot(doc => {
setUserInfo({
id: doc.id,
...doc.data(),
});
});
}
};
useEffect(() => {
setUserData();
}, []);
return { userInfo };
};
export default UserProfile;
Dashboard home file => Example of rendering data from the UserProfile component
import React, { useState } from 'react';
import { Link } from 'react-router-dom';
import sprite from '../../../../assets/sprite.svg';
import UserProfile from '../../../../user-profile/user-profile';
import './home-dashboard.styles.scss';
const HomeDashboard = () => {
const { userInfo } = UserProfile();
const handleCurrentLevel = () => {
return !userInfo || userInfo.currentLevel === undefined ? (
<h1>Welcome! Start your eval to see your level</h1>
) : (
<h1>Current Level: {userInfo.currentLevel}</h1>
);
};
const handleCurrentLevelCard = () => {
return !userInfo || userInfo.currentLevel === undefined
? 'Start a new eval to see your level'
: `You scored a ${userInfo.currentLevel} in your last eval`;
};
return (
<div className="home-dash">
<div className="home-dash__title">{handleCurrentLevel()}</div>
<div className="home-dash__cards">
<div className="home-dash__card-1">
<svg className="icon home-dash__card-icon">
<use href={sprite + '#card-icon-success'}></use>
</svg>
<h3 className="home-dash__card-title">
Latest Eval Results
</h3>
<div className="home-dash__card-result-text">
{handleCurrentLevelCard()}
</div>
<Link to="/eval-quiz">
<button className="home-dash__card-btn--purple">
Start New Eval
</button>
</Link>
</div>
{/* TODO Add resutls to firestore */}
{
<div className="home-dash__card-2">
<svg className="icon home-dash__card-icon">
<use href={sprite + '#card-icon-lightbulb'}></use>
</svg>
<h3 className="home-dash__card-title">
Areas to practice
</h3>
<div className="home-dash__card-result-text">
We recommend working on reading skills
</div>
{/*<button className="home-dash__card-btn--blue">
Practice
</button>*/}
<div className="home-dash__coming-soon">
Coming soon!
</div>
</div>
}
</div>
</div>
);
};
export default HomeDashboard;
Firestore/Firebase setup
import firebase from 'firebase/app';
import 'firebase/firestore';
import 'firebase/auth';
const app = firebase.initializeApp({
apiKey: process.env.REACT_APP_FIREBASE_API_KEY,
authDomain: process.env.REACT_APP_FIREBASE_AUTH_DOMAIN,
projectId: process.env.REACT_APP_FIREBASE_PROJECT_ID,
storageBucket: process.env.REACT_APP_FIREBASE_STORAGE_BUCKET,
messagingSenderId: process.env.REACT_APP_FIREBASE_MESSAGING_SENDER,
appId: process.env.REACT_APP_FIREBASE_APP_ID,
measurementId: process.env.REACT_APP_FIREBASE_MEASUREMENT_ID,
});
export const createUserProfileDocument = async (userAuth, additionalData) => {
if (!userAuth) return;
const userRef = firestore.doc(`users/${userAuth.uid}`);
const snapShot = await userRef.get();
const { displayName, email, photoURL } = userAuth;
const createdAt = new Date();
if (!snapShot.exists) {
console.log(displayName);
try {
await userRef.set({
displayName,
photoURL,
email,
createdAt,
...additionalData,
});
} catch (error) {
console.log('error catching data', error.message);
}
}
if (snapShot.exists) {
try {
await userRef.update({
displayName,
email,
...additionalData,
});
} catch (error) {
console.log('error catching data', error.message);
}
}
return userRef;
};
export const firestore = firebase.firestore();
const googleProvider = new firebase.auth.GoogleAuthProvider();
googleProvider.setCustomParameters({ prompt: 'select_account' });
export const signInWithGoogle = () => auth.signInWithPopup(googleProvider);
export const auth = app.auth();
export default app;
Consider this answer a draft, I've made it public in case you can piece it together but I'll update it with some documentation in the morning.
import { useState, useEffect } from 'react';
import { useAuth } from '../context/auth-context';
import { createUserProfileDocument } from '../firebase.utils';
const UserProfile = () => {
const { currentUser } = useAuth();
const [userInfo, setUserInfo] = useState();
const [loading, setLoading] = useState(true);
useEffect(() => {
if (!currentUser) {
// user is signed out
setUserInfo(null);
setLoading(false);
return;
}
const userRef = /* ... */;
setUserInfo(undefined); // clear stale data
setLoading(true); // update loading status
return userRef.onSnapshot({
next(snapshot) {
if (!snapshot.exists) {
userRef
.set({
/* new data */
})
.catch((err) => {
// TODO: Handle errors
});
return;
}
setUserInfo({
id: snapshot.id,
...snapshot.data(),
});
setLoading(false);
},
error(err) {
// TODO: Handle errors
}
});
}, [currentUser]);
return { userInfo }; // <-- this seems odd? missing loading?
};
export default UserProfile;

React Hook error in array handing in useEffect() and setState does not set the state

I'm having two problems in this code. The first is in the second useEffect. For the reason that I don't understand the useEffect stops working every now and then and causes an error "Cannot read property 'toLowerCase'". Removing the toLowerCase does not solve the problem, but the whole array handling seems to be impossible at that time.
The other problem is in the function addName. setNewName does not set newName. That one I've tried in various kinds of forms, such as setNewName(...newName, {name: '', number: ''}), setNewName('') inside .then and else as well as outside else.
...
import React, {useState, useEffect} from 'react'
import Filter from './components/Filter'
import PersonForm from './components/PersonForm'
import Persons from './components/Persons'
import personService from './services/person'
const App = () => {
const [person, setPerson] = useState([])
const [newName, setNewName] = useState({name: '', number: ''})
const [filteredPerson, setFilteredPerson] = useState([''])
const [searchTerm, setSearchTerm] = useState('')
useEffect(() => {
personService
.getAll()
.then(initialPersons => {
setPerson(initialPersons)
})
}, [])
useEffect( () => {
const results = person.filter( p =>
p.name.toLowerCase().includes(searchTerm) )
setFilteredPerson(results)
},[person,filteredPerson] )
const addName = (event) => {
event.preventDefault()
const nameObject = {
name: newName.name,
number: newName.number
}
if (person.some(p => p.name === newName.name)
) {
window.alert(`${newName.name} is already added to phonebook`)
}
else {
personService
.create(nameObject)
.then(returnedPerson => {
setPerson(person.concat(returnedPerson))
setNewName({name: '', number: ''})
})
console.log('newName', newName.name )
}
}
const handleAddPerson = (event) => {
console.log('event.target.name ', event.target.name)
console.log('event.target.value ', event.target.value)
setNewName({...newName,
[event.target.name]: event.target.value
})
}
const handleSearchTerm = (event) => {
setSearchTerm(event.target.value)
}
return (
<div >
<h2>Phonebook</h2>
<Filter searchTerm={searchTerm} onChange={handleSearchTerm} />
<h3>Add a new</h3>
<PersonForm onSubmit={addName} onChange={handleAddPerson} />
<h2>Numbers</h2>
<Persons list={filteredPerson} />
</div>
);
}
export default App;
...
import axios from 'axios'
const baseUrl = 'http://localhost:3001/persons'
const getAll = () => {
const request = axios.get(baseUrl)
return request.then(response => response.data)
}
const create = newObject => {
const request = axios.post(baseUrl, newObject)
return request.then(response => response.data)
}
const update = (id, newObject) => {
const request = axios.put(`${baseUrl}/${id}`, newObject)
return request.then(response => response.data)
}
/*const updater = {
getAll,
create,
update
}*/
export default {
getAll,
create,
update
}
EDIT
Use async await in your personService so you can return response instead of return request.then(...) something like:
const getAll = async () => {
const response = await axios.get(baseUrl);
return response;
}
After that you can do as follows in your useEffect
useEffect(() => {
(async () => {
const response = await personService.getAll();
if (response.status === 200) {
setPerson(response.data);
const filtered = response.data.filter(item =>
item.name.toLowerCase().includes(searchTerm)
);
setFilteredPerson([...filtered]);
}
})();
}, []);

Resources