Have to run function 2 times for setting value to state in react? - reactjs

Code:-
const [TimeStampsFromFile, setTimeStampsFromFile] = useState([])
const FilePicker = async () => {
var RNFS = require('react-native-fs')
// Pick a single file
try {
const res = await DocumentPicker.pick({
type: [DocumentPicker.types.plainText],
})
const filepath =
RNFS.ExternalStorageDirectoryPath + '/' + 'TimeStamps' + '/' + res.name
const file = await RNFS.readFile(filepath)
setTimeStampsFromFile(await file.split('\n'))
console.log('file data' + TimeStampsFromFile)
} catch (err) {
if (DocumentPicker.isCancel(err)) {
// User cancelled the picker, exit any dialogs or menus and move on
} else {
throw err
}
}
}
this function runs on pressing a button in my react native app:-
On pressing the first time, it needs to return value but it simply returns nothing. But on pressing the second time it returns the value. (Why is that??) or Am I making some mistakes in code??
The same thing is also happing with my other button too.
I found this answer : - hooks not set state at first time but not able to get solution of my problem (if you can help from this answer)

TimeStampsFromFile is empty the first time you log it because setTimeStampsFromFile is async. If you want to log TimeStampsFromFile when value will be updated you could use useEffect hook like:
useEffect(() => {
console.log(TimeStampsFromFile);
}, [TimeStampsFromFile]);
In this way, every time TimeStampsFromFile changes his value, useEffect will be called and log will show current value.
If you need to get the value of the TimeStampsFromFile from FilePicker function, is not necessary to get this value from TimeStampsFromFile. You could do something like:
...
const splitFile = await file.split('\n');
setTimeStampsFromFile(splitFile)
console.log('file data' + splitFile)
...

Related

SvelteKit form get request

I am trying to set up a simple endpoint in SvelteKit that reads the input given in a form and returns the result of an SQL query. In my first attempt I used the form actions and wrote the following code in the +page.server.js file:
export const actions = {
default: async (event) => {
let form_input = await event.request.formData();
let query = {
text: "select * from ux_return_shipments($1, $2, $3, $4)",
values: [form_input.get('beg-dep-date') || null, form_input.get('end-dep-date') || null, form_input.get('beg-arr-date') || null, form_input.get('end-arr-date') || null
}
try {
const result = await event.locals.pool.query(query);
return result.rows;
} catch (e) {
console.log(e);
}
}
};
I am now trying to set up the same process using a GET request instead of a POST one but I am having difficulties setting up the endpoint. I tried to replace the above code with this template but it looks like the endpoint is not getting activated since I see no activity server side:
export function GET({ url }) {
console.log(url);
return new Response("Test response");
};
What am I doing wrong? I see that using this code for an API endpoint (+server.js file) works correctly. I also checked the form element and the URL looks correct.
In case someone has the same problem I managed to solve it using this template:
export const load = async (event) => {
return ...
};
Using the load function I was able to set up a get endpoint and pass some data to the frontend using a return.

React 17 useMemo create a losted instance of object

[EDIT]
Thanks to #dbuchet for his anwser. The problem comes from the fact that in StrictMode in dev mode only, everythings is running twice.
[PROBLEM]
I just got a weird beavour in React.
My context :
I want to create an EventSource for work with Mercure. So i created a hook and this hook store my EventSource with a useMemo. Until here everything's is fine. But after some tests, eachtime i call my hook, two connections are created not only one.
The problem is that i am not able to close the first connection. Only the second. This cause memory leak and undesired persistent connections.
My useMemo for the EventSource :
const eventSource = useMemo(() => {
if (topics.length === 0 || !hubUrl || !baseUrl) {
return null;
}
let url = new URL(hubUrl);
topics.forEach(topic => {
url.searchParams.append('topic', (baseUrl ? baseUrl : '') + topic);
});
return new EventSource(url, {
withCredentials: withCredentials
});
}, [baseUrl, hubUrl, withCredentials, topicsHash]);
After some investigations, i can see that if i add some Math.random(), logs and a simple setInterval, i am able to see that two different objects are created :
const eventSource = useMemo(() => {
if (topics.length === 0 || !hubUrl || !baseUrl) {
return null;
}
let url = new URL(hubUrl);
topics.forEach(topic => {
url.searchParams.append('topic', (baseUrl ? baseUrl : '') + topic);
});
console.log('opening... ' + temp)
let connectionInterval = null;
connectionInterval = setInterval(() => {
console.log('------------- setInterval ---------------')
onsole.log(topics, eventSource, temp);
clearInterval(connectionInterval);
});
let test = { test: temp, eventSource: new EventSource(url, {
withCredentials: withCredentials
})}
return test;
}, [baseUrl, hubUrl, withCredentials, topicsHash]);
The result in the logger is :
So we can see that my useMemo seems to be called only once (due to the fact that 'opening...' log is visible only once). But the random is different of the final object that i have at the end.
Moreover, setInterval is executed twice with both randoms visible.
Maybe something in my project cause this, so i created a simple peice of React and try the code below and same beavour :
const temp = useMemo(() => {
let test = Math.random();
let inter = setInterval(() => {
console.log('setInterval');
console.log(test);
clearInterval(inter);
});
console.log(test);
}, ['for block reloading'])
Result of the console :
Anyone got the same problem ?
Is there a way to avoid this, maybe i made a mistake somewhere or i misunderstood something with useMemo ?
Thanks !

how to turn off buffering in react-player?

when I try to play the next video it does not start and I guess the problem is buffering.
P.S my url is video.m3u8 files
It works fine, but when i change url nothing happens, i would like to know how can i stop current video and load a new one whe, url changes ?
here's my rewind function
const showVideo = async () => {
sessionStorage.setItem("sPlayerLinkId", params.id);
const body = new FormData();
const mac = window.TvipStb.getMainMacAddress();
body.append("link_id", params.id);
body.append("mac", mac);
let response = await fetch(getVideo, {
method: "POST",
body: body,
});
let data = await response.json();
if (data.error) {
openDialog("crush");
return 0;
}
if (_isMounted.current) setVideoLink(data.response.url); };
var goToNext = function () {
playerRef.current.seekTo(0, "seconds");
setVideoLink(null);
if (playerInfo.next_id) {
params.id = playerInfo.next_id;
showVideo();
} else navigate(-1);};
<ReactPlayer
url={videoLink}
playing={isPlaying}
ref={playerRef}
key={params.id}
onProgress={() => {
current();
}}
config={{
file: {
forceHLS: true,
},
}}
/>
I would suggest you build your own player from scratch using just react and a style library.
I had similar issues using react-player and I had to resort to building my own custom player in which I could now ensure that buffering is handled the way I expect it to.
I handled buffering using the progress event as follows
const onProgress = () => {
if (!element.buffered) return;
const bufferedEnd = element.buffered.end(element.buffered.length - 1);
const duration = element.duration;
if (bufferRef && duration > 0) {
bufferRef.current!.style.width = (bufferedEnd / duration) * 100 + "%";
}
};
element.buffered represents a collection of buffered time ranges.
element.buffered.end(element.buffered.length - 1) gets the time at the end of the buffer range. With this value, I was able to compute the current buffer range and update the buffer progress accordingly.
I ended up writing an article that would help others learn to build an easily customizable player from scratch using just React and any style library (in this case charkra UI was used).

Why is this not logging to the console when a reaction is added to a message?

The current code is not logging to the console when a reaction is added to a message.
I know the messageReactionAdd event is triggered by calling the event separately underneath, however I am not sure why this is not logging.
// This makes the events used a bit more readable
const events = {
ADD: 'messageReactionAdd',
REMOVE: 'messageReactionRemove',
};
// This event handles adding/removing users from the role(s) they chose
client.on('raw', async event => {
if (!events.hasOwnProperty(event.t)) return;
const { d: data } = event;
const user = client.users.get(data.user_id);
const channel = client.channels.get(data.channel_id);
const message = await channel.fetchMessage(data.message_id);
const member = message.guild.members.get(user.id);
const emojiKey = (data.emoji.id) ? `${data.emoji.name}:${data.emoji.id}` : data.emoji.name;
let reaction = message.reactions.get(emojiKey);
if (!reaction) {
// Create an object that can be passed through the event like normal
const emoji = new Emoji(client.guilds.get(data.guild_id), data.emoji);
reaction = new MessageReaction(message, emoji, 1, data.user_id === client.user.id);
}
if(event.t === 'ADD') {
console.log("Reaction: Added")
}
});
There is no errors, console completely blank.
For what it seems, you are using if (!events.hasOwnProperty(event.t)) return; to check if event.t is equal to any of them, but when someome react in a message event.t returns MESSAGE_REACTION_ADD. So it's coming back from the beginning.
"Just change the ADD property to fix IT"
But, in if(event.t === 'ADD') you check if event.t is equal to ADD, So this will not execute, since event.p returns MESSAGE_REACTION_ADD
"Just change the if(event.t === 'ADD') to if(event.p === 'MESSAGE_REACTION_ADD) {
Make this to fix your code.

Perform Asynchronous Decorations in DraftJS?

I'm trying to perform real-time Named Entity Recognition highlighting in a WYSIWYG editor, which requires me to make a request to my back-end in between each keystroke.
After spending about a week on ProseMirror I gave up on it and decided to try DraftJS. I have searched the repository and docs and haven't found any asynchronous examples using Decorations. (There are some examples with Entities, but they seem like a bad fit for my problem.)
Here is the stripped down Codepen of what I'd like to solve.
It boils down to me wanting to do something like this:
const handleStrategy = (contentBlock, callback, contentState) => {
const text = contentBlock.getText();
let matchArr, start;
while ((matchArr = properNouns.exec(text)) !== null) {
start = matchArr.index;
setTimeout(() => {
// THROWS ERROR: Cannot read property '0' of null
callback(start, start + matchArr[0].length);
}, 200) // to simulate API request
}
};
I expected it to asynchronously call the callback once the timeout resolved but instead matchArr is empty, which just confuses me.
Any help is appreciated!
ok, one possible solution, a example, simple version (may not be 100% solid) :
write a function take editor's string, send it to server, and resolve the data get from server, you need to figure out send the whole editor string or just one word
getServerResult = data => new Promise((resolve, reject) => {
...
fetch(link, {
method: 'POST',
headers: {
...
},
// figure what to send here
body: this.state.editorState.getCurrentContent().getPlainText(),
})
.then(res => resolve(res))
.catch(reject);
});
determine when to call the getServerResult function(i.e when to send string to server and get entity data), from what I understand from your comment, when user hit spacebar key, send the word before to server, this can done by draftjs Key Bindings or react SyntheticEvent. You will need to handle case what if user hit spacebar many times continuously.
function myKeyBindingFn(e: SyntheticKeyboardEvent): string {
if (e.keyCode === 32) {
return 'send-server';
}
return getDefaultKeyBinding(e);
}
async handleKeyCommand(command: string): DraftHandleValue {
if (command === 'send-server') {
// you need to manually add a space char to the editorState
// and get result from server
...
// entity data get from server
const result = await getServerResult()
return 'handled';
}
return 'not-handled';
}
add entity data get from server to specific word using ContentState.createEntity()
async handleKeyCommand(command: string): DraftHandleValue {
if (command === 'send-server') {
// you need to manually add a space char to the editorState
// and get result from server
...
// entity data get from server
const result = await getServerResult()
const newContentState = ContentState.createEntity(
type: 'string',
mutability: ...
data: result
)
const entityKey = contentStateWithEntity.getLastCreatedEntityKey();
// you need to figure out the selectionState, selectionState mean add
// the entity data to where
const contentStateWithEntity = Modifier.applyEntity(
newContentState,
selectionState,
entityKey
);
// create a new EditorState and use this.setState()
const newEditorState = EditorState.push(
...
contentState: contentStateWithEntity
)
this.setState({
editorState: newEditorState
})
return 'handled';
}
return 'not-handled';
}
create different decorators find words with specific entity data, and return different style or whatever you need to return
...
const compositeDecorator = new CompositeDecorator([
strategy: findSubjStrategy,
component: HandleSubjSpan,
])
function findSubjStrategy(contentBlock, callback, contentState) {
// search whole editor content find words with subj entity data
// if the word's entity data === 'Subj'
// pass the start index & end index of the word to callback
...
if(...) {
...
callback(startIndex, endIndex);
}
}
// this function handle what if findSubjStrategy() find any word with subj
// entity data
const HandleSubjSpan = (props) => {
// if the word with subj entity data, it font color become red
return <span {...props} style={{ color: 'red' }}>{props.children}</span>;
};

Resources