Using web socket(#aspnet/signalr) it works fine(in component callback is receiving the message)fine, I am able to receive and trigger callback in component(connection.on("UpdateProgress"... ) inside this callback its increment counter which is state variable(numberOfFailed).. it triggers rendering only once, I set debugger and see numberOfFailed is always 0.
What's wrong here? why calling setNumberOfFailed doesn't change the value of numberOfFailed.
here is the code;
const [numberOfFailed, setNumberOfFailed] = useState(0);
const [connection, setConnection] = useState(null);
useEffect(() => {
const newConnection = new HubConnectionBuilder()
.withUrl(`${config.API_BASE_URL}update-progress`, {
transport: HttpTransportType.WebSockets,
accessTokenFactory: () => {
return `${localStorage.token}`;
},
})
.build();
setConnection(newConnection);
}, []);
useEffect(() => {
const fetchData = async () => {
if (connection) {
try {
await connection.start();
connection.onclose((error) => {
console.info('Connection Closed:', error);
});
if (connection.state === HubConnectionState.Connected) {
connection.on('UpdateProgress', (message) => {
debugger;
if (message.count) {
setTitleText(`Bildirim Gonderim Başladı, Toplam Alıcı Sayısı:${message.count}`);
} else if (message.status == 1) {
let _t = numberOfFailed + 1;
setNumberOfFailed(_t);
}
console.info('message', message);
});
}
} catch (err) {
console.log(err);
}
}
};
fetchData();
}, [connection]);
It was because react not trace the updated of variables which not explicitly defined in DependencyList. The best solution for this change the way..
This is how I solve this problem;
The main idea is using useReducer hook to update variables and use them in render.
const [connection, setConnection] = useState(null);
const [counts, dispatch] = useReducer(BaskentMobilReducer, INITIAL_VALUE);
useEffect(() => {
const newConnection = new HubConnectionBuilder()
.withUrl(`${config.API_BASE_URL}update-progress`, {
transport: HttpTransportType.WebSockets,
accessTokenFactory: () => {
return `${localStorage.token}`;
},
})
.build();
setConnection(newConnection);
}, []);
useEffect(() => {
const fetchData = async () => {
if (connection) {
try {
await connection.start();
connection.onclose((error) => {
console.info("Connection Closed:", error);
});
if (connection.state === HubConnectionState.Connected) {
connection.on("UpdateProgress", (message) => {
if (message.count) {
setTotalCount(message.count);
setTitleText(
`Bildirim Gonderim Başladı, Toplam Alıcı Sayısı:${message.count}`
);
} else if (message.status == 0) {
debugger;
dispatch({
type: "UPDATE_COUNTS_SUCCESS",
});
console.log("counts", counts);
} else if (message.status == 1) {
debugger;
dispatch({
type: "UPDATE_COUNTS_FAIL",
});
console.log("counts", counts);
}
console.info("message", message);
});
}
} catch (err) {
console.log(err);
}
}
};
fetchData();
}, [connection]);
Related
I know what caused this error, I explicitly removed the header from axios call to check if the code can handle the error. But my question is I have a catch block in place, but I'm still getting this -> Possible Unhandled Promise Rejection
const getUser1 = () => {
userService.getUser1().then((res) => {
setId(res.data._id);
return Promise.resolve();
}).catch((error) => Promise.reject(error));
};
const getUserComments = () => {
commentsService.getUserComments(‘user1’).then((res) => {
setComments(res.data)
return Promise.resolve();
}).catch((err) => Promise.reject(err));
};
useEffect(() => {
const onInit = async () => {
await Promise.all([
getUser1(),
getUserComments(),
]).catch((ex) => console.log(ex));
};
onInit();
}, []);
Try this version:
const getUser1 = async () => {
try{
const {data} = await userService.getUser1()
setId(data._id);
}
catch(err){
throw new Error(err)
}
};
const getUserComments = async () => {
try{
const {data} = await commentsService.getUserComments(‘user1’)
setComments(data)
}
catch(err){
throw new Error(err)
}
};
const init = useCallback(async () =>{
try{
return await Promise.all([
getUser1(),
getUserComments(),
])
}
catch(err){
console.error(err)
}
}, [])
useEffect(() => {
init();
}, [init]);
In case of no cache, infinite scroll works, but when you add cache code, the data repeats when pagination is finished. how can i solve. I am doing a clone project. I'm new to redis, I'd be very grateful if you could reply. I can't think of anything about it (:
Backend my code
const searchpost = async (req, res) => {
let perpage = 3;
const value = req.query.q;
const pageNumber = req.query.page;
try {
const redisPosts = await client.keys("Blog*");
if (redisPosts.length > 0) {
async.map(
redisPosts,
async function (redisPost) {
const cacheBlog = await client.get(redisPost);
let parseData = JSON.parse(cacheBlog);
let job = { ...parseData };
return job;
},
function (err, results) {
if (err) throw err;
res.status(200).json({ searcharticles: results });
}
);
} else {
const searcharticles = await Blog.find({
$or: [
{ title: { $regex: value, $options: "i" } },
{ tag: { $regex: value, $options: "i" } },
{ Subtitle: { $regex: value, $options: "i" } },
],
})
.skip((pageNumber - 1) * perpage)
.limit(perpage)
.populate("authorId");
async.map(
searcharticles,
async function (searcharticle) {
let cacheKey = `Blog:` + uuidv4();
await client.set(cacheKey, JSON.stringify(searcharticle));
return searcharticles;
},
function (err, searcharticles) {
if (err) throw err;
res.status(200).json({ searcharticles });
}
);
}
} catch (err) {
res.status(401).json({ message: "hata durumu oluştu" });
}
};
infinity scroll react code
export const SearchPost = (query, pageNumber) => {
const [loading, setLoading] = useState(true);
const [error, setError] = useState(false);
const [blogs, setBlogs] = useState([]);
const [hasMore, setHasMore] = useState(false);
const [userInfo, setuserInfo] = useState();
useEffect(() => {
setBlogs([]);
}, [query]);
useEffect(() => {
setLoading(true);
setError(false);
let cancel;
axios({
method: "GET",
url: `/api/search`,
params: { q: query, page: pageNumber },
withCredentials: true,
cancelToken: new axios.CancelToken((c) => (cancel = c)),
})
.then((res) => {
console.log(res.data);
setBlogs((prevBlog) => {
return [
...new Set([...prevBlog, ...res.data.searcharticles.map((b) => b)]),
];
});
setHasMore(res.data.searcharticles.length);
setLoading(false);
setuserInfo(res.data.userInfo);
})
.catch((err) => {
if (axios.isCancel(err)) return;
setError(true);
});
return () => cancel();
}, [query, pageNumber]);
return { loading, error, blogs, hasMore, userInfo };
};
const [query, setQuery] = useState("");
const [pageNumber, setPageNumber] = useState(1);
const { ısAuthenticated } = useContext(AuthContext);
const { blogs, hasMore, loading } = SearchPost(query, pageNumber);
const observer = useRef();
const lastBlogElementRef = useCallback(
(node) => {
if (loading) return;
if (observer.current) observer.current.disconnect();
observer.current = new IntersectionObserver((entries) => {
if (entries[0].isIntersecting && hasMore) {
//burda verıyı gecıp gecmedıgını kontrol etmelıyız
setPageNumber((prevPageNumber) => prevPageNumber + 1);
}
});
if (node) observer.current.observe(node);
},
[loading, hasMore]
);
function handleSearch(e) {
setQuery(e.target.value);
setPageNumber(1);
}
I'm writing for those who encounter this problem, you don't need to do a for loop. You can do this by typing the number of pages into the key. The edited code is below.
const searchpost = async (req, res) => {
let perpage = 3;
const value = req.query.q;
const pageNumber = req.query.page;
const query = `Blog:` + "/" + pageNumber;
try {
let redisPosts = await client.get(query);
if (redisPosts) {
redisPosts = JSON.parse(redisPosts);
res.status(200).json({ searcharticles: redisPosts });
} else {
const searcharticles = await Blog.find({
$or: [
{ title: { $regex: value, $options: "i" } },
{ tag: { $regex: value, $options: "i" } },
{ Subtitle: { $regex: value, $options: "i" } },
],
})
.skip((pageNumber - 1) * perpage)
.limit(perpage)
.populate("authorId");
let cacheKey = query;
await client.set(cacheKey, JSON.stringify(searcharticles));
res.status(200).json({ searcharticles });
}
} catch (err) {
res.status(401).json({ message: "hata durumu oluştu" });
}
};
I'm using "#microsoft/signalr": "^6.0.5", and trying to set up a connection.
It is able to connect with the backend, but I am not sure if my setup looks OK for when the connection fails.
Specifically, I am wondering if the last useEffect is correctly written (the placement of the onClose clause)
useEffect(() => {
const newConnection = new HubConnectionBuilder()
.withUrl(
"https://localhost:3000/workorderHub",
{ accessTokenFactory: () => token, withCredentials: false }
)
.configureLogging(LogLevel.Information)
.withAutomaticReconnect()
.build();
setConnection(newConnection);
}, []);
useEffect(() => {
async function start() {
if (connection) {
try {
connection
.start()
.then(() => {
connection.invoke("SubscribeToProject", projectId); // calling hub method from the client
})
.catch((err) => {
console.error(err.toString());
});
connection.on(
"OperationUpdated",
(projectId, operationId, operation) => {
// function called from the backend Hub
actions.updateSyncedOperation({ operationId, operation });
}
);
} catch (err) {
console.log({ err });
setTimeout(start, 5000);
}
} else {
connection.onclose(async () => {
await start();
});
}
}
start();
}, [connection]);
For React 18 with the new strictMode behaviour i do the following.
It only creates one connection without any errors and it seems to cleanup properly during strictmode behaviour.
export const useLiveUpdates = () => {
const [connectionRef, setConnection] = useState < HubConnection > ();
function createHubConnection() {
const con = new HubConnectionBuilder()
.withUrl(`${EnvService.getUrlHub('url')}`, {
accessTokenFactory: () => AuthService.getToken(),
})
.withAutomaticReconnect()
.build();
setConnection(con);
}
useEffect(() => {
createHubConnection();
}, []);
useEffect(() => {
if (connectionRef) {
try {
connectionRef
.start()
.then(() => {
connectionRef.on('message', () => { ...
});
})
.catch((err) => {
logger.error(`Error: ${err}`);
});
} catch (error) {
logger.error(error as Error);
}
}
return () => {
connectionRef ? .stop();
};
}, [connectionRef]);
};
loadMoreMessages this is being called when the scrollTop gets to 0. and calling setScrollPosition but the useEffect is not being called.
setMessages is working fine
const [scrollPosition, setScrollposition] = useState('')
const { messages, setMessages } = useMessages()
let getMessages = ({onSuccess, onError, finaly = f => f}) => {
socket.emit('get:messages', (err, respo) => {
if(err) {
onError(err)
}
else {
console.log('respo ', respo)
else {
onSuccess(respo)
}
}
})
}
let loadMoreMessages = () => {
getMessages({
onError: err => console.log(err),
onSuccess: data => {
setMessages({
type: 'update',
data
})
console.log('messages updated') // the code dose reach here
setScrollposition('update')
}
})
}
useEffect(() => {
console.log(scrollPosition)
}, [scrollPosition])
might you can do this
useEffect(()=>{
if(scrollPosition === 'something'){
loadMoreMessages();
}
},[scrollPosition])
I am new in react native and try to call two api from useEffect but it give me this error every time React Hook useEffect has a missing dependency: 'getAllPost'. Either include it or remove the dependency array.
Here is my code
export default function Home({navigation}) {
const [arrCat, setArrCat] = useState([]);
const [arrPost, setArrPost] = useState([]);
const [isLoading, setLoding] = useState(false);
function getAllCategory() {
setLoding(true);
let apiResponse = ApiManager.GET('category/all', [], 'GET');
apiResponse
.then(response => {
let responseJson = response[1];
let status = response[0];
setLoding(false);
let message =
responseJson.message != null
? response.message
: 'Something went wrong';
if (status === 200) {
setArrCat([...responseJson.data]);
getAllPost();
}
setTimeout(function() {
if (message != null) {
Toast.showWithGravity(message, Toast.LONG, Toast.BOTTOM);
}
}, 120);
})
.catch(error => {
console.error(error);
Toast.showWithGravity(error, Toast.LONG, Toast.BOTTOM);
setTimeout(function() {
setLoding(false);
}, 60);
});
}
function getAllPost() {
GetLocation.getCurrentPosition({
enableHighAccuracy: true,
timeout: 15000,
})
.then(location => {
console.log(location);
const dictData = {
lat: '-37.81400200-33.865143', //location.latitude,
lang: '144.9546943', //location.longitude,
record_count: '0',
};
console.log(dictData);
let apiResponse = ApiManager.POST(
'post/getRecommendedPost',
dictData,
'POST',
);
apiResponse
.then(response => {
let responseJson = response[1];
let status = response[0];
if (status === 200) {
console.log(responseJson);
setArrPost(oldValue => [...oldValue, ...responseJson.data]);
console.log(arrPost);
} else {
// console.error(responseJson);
Toast.showWithGravity(
responseJson.message,
Toast.LONG,
Toast.BOTTOM,
);
}
})
.catch(error => {
// console.error(error);
Toast.showWithGravity(error.message, Toast.LONG, Toast.BOTTOM);
// setTimeout(function() {
// setLoding(false);
// }, 60);
});
})
.catch(error => {
// const {code, message} = error;
// console.warn(code, message);
Toast.showWithGravity(error.message, Toast.LONG, Toast.BOTTOM);
});
}
useEffect(() => {
console.log('Home screen mounted');
getAllCategory();
// getAllPost();
}, []);
return ( ....)
}