how to apply Full screen striction in react js? - reactjs

Here i am developing an examination system. I want to apply full screen when i launch exam component.
While doing student strict to remain in full screen. When he/she exit from full screen then automatically call a function to save exam result.

There are some limitations when it comes to displaying things fullscreen but I suggest you to use https://github.com/sindresorhus/screenfull.js . It's quite well maintained and makes it easier for you to support multiple browsers.
In React you could do something like this:
// import/exports depend on your setup, this is just an example
const screenfull = require('screenfull');
class MyComponent extends React.Component {
componentDidMount() {
if (screenfull.isEnabled) {
screenfull.on('change', () => {
console.log('Am I fullscreen?', screenfull.isFullscreen ? 'Yes' : 'No');
});
}
}
// enabling fullscreen has to be done after some user input
toggleFullScreen = () => {
if (screenfull.isEnabled) {
screenfull.toggle();
}
}
render() {
return (
<button onClick={this.toggleFullScreen}>Toggle fullscreen</button>
)
}
}
LE:
To detect a fullscreen change you can use the screenfull.on('change') event: https://github.com/sindresorhus/screenfull.js#detect-fullscreen-change
Added code for this in the above example.

Related

How to detect if the React app is actually being viewed

So I have created an app that shows data in realtime obtaining it from devices.
However, I want to make my server not obtain data when nobody is viewing the app.
So essentially I need some way to determine whether the app is currently being viewed, regardless of if it's desktop or mobile, this includes tab is on focus where the app is opened and that is what the user is currently viewing, and there is nothing on top of the browser, so browser opened on the correct tab, but user has explorer on top of it doing something entirely different, this for my case should be false, and for mobile, the same thing including if device is locked (screen off).
The reason for trying to do that, is to reduce the load on the devices, so that data is being requested, only when there is someone to view it.
From what I have researched I found out about the focus and blur events, but I was unable to make it work, and I don't even know if that is the correct approach, but what I have tried is:
Adding event listeners to the window in the App component:
function App() {
useEffect(() => {
window.addEventListener("focus", () => { console.log("viewed")});
window.addEventListener("blur", () => { console.log("hidden")});
})
}
Adding them as props to the App component within index.js:
<App onFocus={() => {console.log("viewed")}} onBlur={() => {console.log("hidden")}}/>
Neither had any kind of effect, I didn't get either of the console outputs.
Is that even the correct approach?
I would add a socket connection to the app. Then the server would be able to know if there are at least X persons connected and act accordingly.
I would suggest you to try socket for this kind of connection tested, but since you also wanna reduce the load for the user, testing if the user is focused in the browser is the way to go.
To achieve it, I won't add this code inside the React component because of the nature of React as all of its components are rendered inside the <div id="root"></div>, other parts of the html page will still be unaffected by this mechanism. So what you probably want to do is to add the code in the index.html and use window.userFocused to pass the value into React from the index
Edit: added focus/blur script
<script>
window.addEventListener("focus", function(event)
{
console.log("window is focused");
window.userFocused = true;
}, false);
window.addEventListener("blur", function(event)
{
console.log("window is blurred");
window.userFocused = false;
}, false);
</script>
So I ended up solving it with pretty much the same code as initiallywith a few slight modifications, I still used an useEffect hook:
const onFocusFunction = () => {
// do whatever when focus is gained
};
const onBlurFunction = () => {
// do whatever when focus is lost
};
useEffect(() => {
onFocusFunction();
window.addEventListener("focus", onFocusFunction);
window.addEventListener("blur", onBlurFunction);
return () => {
onBlurFunction();
window.removeEventListener("focus", onFocusFunction);
window.removeEventListener("blur", onBlurFunction);
};
}, []);
The best way is to use document.
document.onvisibilitychange = () => {
console.log(document.hidden)
}

Why do these two pieces of Hello World code differ in behaviour?

I am new to both JavaScript and ReactJS and want to understand why the following pieces of code differ in behaviour:
class App extends React.Component
{
render()
{
return (
<button onClick={() => {alert("Hello World!");}}>Hello!</button>
);
}
};
The above code works as expected. A button is shown on the page, and when the button is clicked an alert message "Hello World!" is displayed.
But the following code does not work as expected:
class App extends React.Component
{
alertText = (text) => {
alert(text);
}
/*
alertText(text) {
alert(text);
}
*/
render()
{
return (
<button onClick={this.alertText("Hello World!")}>Hello!</button>
);
}
};
I was expecting this code to work similar to the first piece of code. Instead, two alert messages with the text "Hello World!" are displayed in succession immediately after the page is launched without the button being clicked. But after that nothing happens when the button is clicked.
My platform is Ubuntu 20.04.1, nodejs is v10.19.0 and npx is 6.14.4, browser is Firefox 80.0 Ubuntu build. I created the React app with npx create-react-app command.
Because the code tell them to behave differently. onClick expect a function. this.alertText("Hello World!") is not a function, you just call the function right away. It should be
render()
{
return (
<button onClick={() => this.alertText("Hello World!")}>Hello!</button>
);
}
well because you always call functions in your render, in the first one you call arrow function which returns the alrt function which would be called on click, on the other hand you call directly the alert.

Why does my screen not update when I click my button the first time, but works perfectly fine afterwards?

This is my first time making a finite state Automata. I tried making a stop light kind of program where if you click the button, the light changes once, starting at green, then to yellow if clicked again, then to red, before looping again. I managed to make it work, except for one small bug. It needs to be clicked twice before the screen updates, and I don't really know how to fix it.
I noticed on my console that the currentLightState changes when I click on it, but reverts back to the previous color on the first click. I figured out that it's because it is not in sync with my state. However, when I attempt to put currentLightState inside the class, and assign this.state.light, currentLightState becomes undefined. I tried adding a .bind(this) at the end of this.state.light, but I just get another error saying it's not a function. Any suggestions?
I didn't post my update function or my onHandleClick function since it doesn't directly deal with currentLightState.
const lightMachine = {
green:{
LIGHT: 'yellow'
},
yellow:{
LIGHT: 'red'
},
red:{
LIGHT: 'green'
}
}
// current location of currentLightState
let currentLightState = 'green';
class App extends React.Component{
constructor(props){
super(props);
this.state = {
light: 'green' //initial value
};
}
transition(state, action){
// This is where my currentLightState messes up the first run
currentLightState = this.state.light
const nextLightState = lightMachine[currentLightState][action]
this.setState({light: nextLightState})
}
render(){
return(
<div>
<button onClick={this.onHandleClick.bind(this)}>
change the Light!
</button>
{currentLightState}
</div>
);
}
}
EDIT: Here is my onHandleClick function :)
onHandleClick(){
this.update(currentLightState)
};
also, I think I solved my problem by just substituting the currentLightState in the render function with this.state.light .
Idk if that is a legitimate fix or not, but it seems to work currently.
it would be nice though if someone can still answer why when you put the currentLightState inside the class, and assign state.light to it, it becomes undefined. It would help expand my React knowledge :)
Welcome to the boards Jr194!
On topic, I think it will be beneficial to keep currentLight and lightMachine as values managed by your component state. This helps ensure all your logic is within the same context, avoiding weird errors like "blah blah is not defined."
Second, you seem to have defined a few functions that can really be narrowed down to one. update, onHandleClick and transition all seem to be trying to do the same thing.
Lastly, consider reorganizing the code in your lightMachine to be a bit more intuitive so that you can quickly navigate to the next light. You already know what the current color is in the parent key, is their really a need for having its object contain another key with the same value?
Consider the following code:
class App extends React.Component {
state = {
currentLight: "green",
lightMachine: {
green: {
nextLight: "yellow"
},
yellow: {
nextLight: "red"
},
red: {
nextLight: "green"
}
}
};
transition = () => {
const currentLight = this.state.currentLight;
const nextLight = this.state.lightColors[currentLight].nextLight;
this.setState({
currentLight: nextLight
});
};
render() {
return (
<div>
<button onClick={this.transition}>Click Me</button>
<div>{this.state.currentLight}</div>
</div>
);
}
}
This should let you quickly change lights as expected. And here's the sandbox: https://codesandbox.io/s/4x08ovyjp7
Let me know if you have any questions :)
Also regarding your question about why currentLightState gives you an error in your render when you put it inside the class. This is not a React issue, it's a JavaScript issue.
Let's go through some examples:
const test= "hello"
class Example extends React.Component{
state = {
greeting: "woof"
}
render(){
<div>{test}</div>
}
}
As you know, this won't give us any error. We are tapping into the variable that's defined outside our class and that's completely fine.
Now let's see look at this
class Example extends React.Component{
state = {
greeting: "woof"
}
test = this.state.greeting
render(){
<div>{test}</div>
}
}
This gives us an error. Why, because in your render method, you are treating test like it's a variable, when it is not. In a class object like the one you have written, currentLightState and now test are treated as properties, not variables. In order to get access to a property inside a class, you need to make use of the "this" keyword, something you already have been doing with this.update, this.handleOnClick and etc, which are also properties.
Now we know this code will work.
class Example extends React.Component{
state = {
greeting: "woof"
}
test = this.state.greeting
render(){
<div>{this.test}</div>
}
}

Design For Loading Components

I am struggling with the design of a React application which I am building. The app has a chat window on the left and the content of the application on the right. When a user enters a command, the backend understands the nature of the command (uses Luis.ai and Microsoft Bot Framework) which all works as expected. However the React piece is where I'm struggling.
Say the user enters a command which states they want to update a person by entering "Update name to Bill". The application correctly understands that the command is update the person and should load the edit version of my person overview.
However I'm not sure exactly the best approach on how to do this. The approach I'm taking now basically loads an OverviewWrapper component. Inside of the Overview wrapper component based on the props passed to it should load either the Edit or the View pane. The View pane is loaded by default.
I guess I'm not sure if I should be trying to load the edit component by changing the state or if I should be trying to use the navigate function. Thank you in advance for your guidance.
Here is my code.
export default class Patient extends React.Component {
constructor(props) {
super(props);
autoBind(this);
this.directLine = new DirectLine({
secret: "SOMEVALUEHERE"
});
this.state = {
PATIENT: [],
COMPPROPS: [],
};
this.setPanelState = this.setPanelState.bind(this);
}
//Set State of COMPPROPS so that compState should be edit
setPanelState(activity) {
var _compState = 'Edit';
var _compName = 'Overview';
this.setState({COMPPROPS: [{compName: 'Overview', compState: _compState}]});
return _compState;
}
componentWillMount() {
getPatient().then((result) => {
this.setState({PATIENT: result});
});
//review any chat activity and if the command is update patient then run setpanelstate method which should set the state
this.directLine.activity$
.filter(function (activity) {
return activity.type === 'event' && activity.value === 'Update Patient';
})
.subscribe((activity) => {
console.log("Im editing the overview");
var _compState2
_compState2 = this.setPanelState(activity);
console.log('CompStateVar:'+_compState2)
})
}
render() {
const OverviewWrapper = this.state.COMPPROPS.compState === 0 ? OverviewEditPane: OverviewPane
return (
...
<Box colorIndex='light-2' direction='row' flex={false}>
<div>
<OverviewWrapper overview={this.state.PATIENT} ovtype={this.state.COMPPROPS} />
</div>
</Box>
I resolved this by keeping the existing design by only setting one value compState in the SetState value rather then trying to set both compName and compState. Once I did that everything seemed to work fine.

ReactJS: componentWillUnmount not working across project

I have an issue with ReactJS. Specifically componentWillUnmount is not being called across the project at all (a semi-large corporate website). I will list the steps I have taken to diagnose and pinpoint the issue:
I am using a simple console.log message to test, to exclude problems inside the function
I have placed it in different jsx files in the project, to exclude function positioning problems
I have checked against switching pages in the app and loading a different website altogether
I checked to see whether the function is called from parents, siblings or children, since I've found competing lifecycle calls can cause neither to work, but it's the only one in the project so far
I tried it on a different branch with no effect
I tried it on a colleague's computer with no effect
A different lifecycle function (componentWillMount) works fine
I am using ES6 with react 15.1.0, react-bootstrap and react-validation. The relevant code is below, but keep in mind I have placed the function in numerous places and it does not appear to get called anywhere.
export default class YourData extends React.Component {
constructor(props){
super(props);
this.getMainBookers = this.getMainBookers.bind(this);
this.bookingTravelCompanyForms = this.props.your_data.bookings.map(
(booking, i) => {
var mainBookers = i > 0 ? this.getMainBookers : false;
return (
<BookingTravelCompanyForm booking={booking} key={i}
mainBookers={mainBookers}
onInputChange={this.props.onInputChange}/>
);
}
);
}
componentWillMount(){
this.props.initializeInput();
}
componentWillUnmount(){
console.log('willunmount yourdata');
this.props.saveInput();
}
getMainBookers() {
var mainform = this.bookingTravelCompanyForms[0];
return mainform.props.booking.company;
}
handleSubmit(event) {
event.preventDefault();
// Emulate async API call
setTimeout(() => {
this.refs.form.showError('username', <span onClick={this.removeApiError.bind(this)}
className='form-error is-visible'>API Error. Click to hide out.</span>);
}, 1000);
}
copyTravelCompany() {
var travelCompany = this.bookingTravelCompanyForms[0];
this.setState({
travelCompany: travelCompany
});
}
render() {

Resources