React How to use different states with click event - javascript

In short:
I'm implementing Simon-Says game app in React Native. (user sees a sequence of flashing buttons, needs to press the buttons in the correct order).
I want to know how to use 2 different states in TouchableOpacity, one of them as a condition to press the button, one for changing the style of the button, and also being notified for this specific press.
So,
I'm having a problem to implement the playerTurn(),
because I'm not sure how to pass the canPress state to the TouchableOpacity button,
considering I'm passing style state that changes in compTurn()
(function that shows a sequence of flashing buttons - then computer turn's over)
In the player turn, things I need to consider:
after the state canPress changes, the user will be allowed to press on the buttons
user presses one of the 4 buttons
the method playerTurn() will be notified which button did the player pressed. (I'm asking how can I get that notification from the button to the method?)
after that, I can push it's choice to the playerSeq array (if pressed green - pushes 1, etc) and call function that changes the style state (greenFlash for example)
code in short :
export default class App extends Component{
constructor (props){
super(props);
this.seq=[1,2,3,1,4] //will be random, this is just for testing
this.playerSeq=[]
...
this.state = {
canPress: false,
greenB: {
backgroundColor: 'darkgreen'
}, ...
playerTurn(){
this.setState({canPress: true})
// if the user pressed on the green button, then I push 1 to the playerSequence
// More functionality will be here
}
render(){
return (..
<TouchableOpacity style={[styles.greenB, this.state.greenB]}></TouchableOpacity>
//I ALSO WANT TO PASS THE STATE CANPRESS + NOTIFY PLAYERTURN() THAT THE USER PRESSED ON THIS BUTTON
Full code: (not the full game, note that I'm learning react just in the past few days)
export default class App extends Component{
constructor (props){
super(props);
this.flash=0
this.round=1
this.seq=[1,2,3,1,4] //will be random, this is just for testing
this.playerSeq=[]
this.win=false
this.ok=true
this.score=0
this.state = {
canPress: false,
greenB: {
backgroundColor: 'darkgreen'
},
yellowB: {
backgroundColor: 'orange'
},
blueB: {
backgroundColor: 'blue'
},
redB: {
backgroundColor: 'red'
}
}
this.play=this.play.bind(this)
this.greenFlash=this.greenFlash.bind(this)
this.blueFlash=this.blueFlash.bind(this)
this.redFlash=this.redFlash.bind(this)
this.playerTurn=this.playerTurn.bind(this)
}
play(){
this.flash=0
this.round=1 //round will increase, this is just for test
this.win=false
this.ok=true
this.score=0
this.compTurn();
this.playerTurn();
}
playerTurn(){
this.setState({canPress: true})
}
compTurn() {
let intervalId = setInterval(()=> {
if (this.flash==this.round) {
clearInterval(intervalId);
}
else {
if (this.seq[this.flash]==1){
this.greenFlash();
}
if (this.seq[this.flash]==2){
this.yellowFlash();
}
if (this.seq[this.flash]==3){
this.blueFlash();
}
if (this.seq[this.flash]==4){
this.redFlash();
}
this.flash++;
}
}
, 1500);
}
greenFlash(){
setTimeout(() => {
this.setState( {
greenB:{
...this.state.style1, backgroundColor: 'lightgreen'
}
})
}, 200);
setTimeout(() => {
this.setState( {
greenB:{
...this.state.style1, backgroundColor: 'darkgreen'
}
})
}, 1000);
}
yellowFlash(){
setTimeout(() => {
this.setState( {
yellowB:{
...this.state.style1, backgroundColor: 'yellow'
}
})
}, 200);
setTimeout(() => {
this.setState( {
yellowB:{
...this.state.style1, backgroundColor: 'orange'
}
})
}, 1000);
}
blueFlash(){
setTimeout(() => {
this.setState( {
blueB:{
...this.state.style1, backgroundColor: 'lightblue'
}
})
}, 200);
setTimeout(() => {
this.setState( {
blueB:{
...this.state.style1, backgroundColor: 'blue'
}
})
}, 1000);
}
redFlash(){
setTimeout(() => {
this.setState( {
redB:{
...this.state.style1, backgroundColor: 'pink'
}
})
}, 200);
setTimeout(() => {
this.setState( {
redB:{
...this.state.style1, backgroundColor: 'red'
}
})
}, 1000);
}
render(){
return (
<View>
<TouchableOpacity style={styles.playB}
onPress={this.play}>
<Text style={{
color:'white',
height: 30,
width:60,
}}>START</Text>
</TouchableOpacity>
<TouchableOpacity style={[styles.greenB, this.state.greenB]}></TouchableOpacity>
<TouchableOpacity style={[styles.yellowB, this.state.yellowB]}></TouchableOpacity>
<TouchableOpacity style={[styles.blueB, this.state.blueB]}></TouchableOpacity>
<TouchableOpacity style={[styles.redB, this.state.redB]}></TouchableOpacity>
</View>
);
}
}
const styles = StyleSheet.create({
greenB:{
padding: 5,
height: 80,
width: 80,
borderRadius:160,
},
yellowB:{
padding: 5,
height: 80,
width: 80,
borderRadius:160,
},
blueB:{
padding: 5,
height: 80,
width: 80,
borderRadius:160,
},
redB:{
padding: 5,
height: 80,
width: 80,
borderRadius:160,
},
playB:{
alignSelf: 'center',
backgroundColor: 'blue',
}
});

Looks like you want to enable clicking on the buttons if state.canPress = true right? Then upon clicking, you wish to notify by calling playerTurn()?
You can do something like this for e.g your green button.
<TouchableOpacity style={[styles.greenB, this.state.greenB]} onPress={this.state.canPress && () => {
this.playerTurn(1);
// Whatever you want to do on green button pressed by player in here.
}>
</TouchableOpacity>
this.setState also has a callback function as its second parameter, which may be more useful in your flash method.

Related

How to make Data and Vuex reactive?

There is such a code:
<template>
<div class="chart"
v-bind:style="chartStyleObject">
</div>
</template>
<script>
export default{
data () {
return {
chartStyleObject: {
width: this.$store.state.chartStyleObject.width,
height: this.$store.state.chartStyleObject.height,
marginTop: this.$store.state.chartStyleObject.marginTop,
marginRight: this.$store.state.chartStyleObject.marginRight,
marginBottom: this.$store.state.chartStyleObject.marginBottom,
marginLeft: this.$store.state.chartStyleObject.marginLeft,
},
},
}
}
And such a repository:
const axios = require("axios");
export const state = () => ({
chartStyleObject: {
height: '247px',
width: '500px',
marginTop: '15px',
marginRight: '0px',
marginBottom: '0px',
marginLeft: '15px',
},
});
export const mutations = {
changeChartDraggableEventState (state, EventState) {
state.chartDraggableEventState = EventState;
},
changeChartHeight (state, height) {
state.chartStyleObject.height = height;
},
changeHeightWrapper (state, HeightWrapper) {
state.chartStyleObject.HeightWrapper = HeightWrapper;
},
changeWidthWrapper (state, WidthWrapper) {
state.chartStyleObject.WidthWrapper = WidthWrapper;
},
changeChartMarginLeft (state, MarginLeft) {
state.chartStyleObject.marginLeft = MarginLeft;
},
changeChartMarginTop (state, MarginTop) {
state.chartStyleObject.marginTop = MarginTop;
},
};
Problem:
If I change the state of the repository through mutations, then the properties of the repository change correctly.
But!
The data properties on which the same storage properties are tied for some reason does not change.
(Despite the fact that repository property was changed)
My question is:
Why does this happen - if dates property, as well as repositories property, in theory, should be reactive?
And which approach is the most correct in this case to solve this problem? (writing directly the storage properties in the code seems like a very cumbersome decision.)
When you assign the values in
chartStyleObject: {
width: this.$store.state.chartStyleObject.width, // here
height: this.$store.state.chartStyleObject.height,
marginTop: this.$store.state.chartStyleObject.marginTop,
marginRight: this.$store.state.chartStyleObject.marginRight,
marginBottom: this.$store.state.chartStyleObject.marginBottom,
marginLeft: this.$store.state.chartStyleObject.marginLeft,
},
you are assigning values to the width, height and so on. You assign to them the current values of the state variables.
If you want the properties of chartStyleObject to change whenever the store's state changes, either map the state directly in the template (or wheverever you use it) or create a computed:
export default {
computed: {
chartStyleObject() {
return {
width: this.$store.state.chartStyleObject.width,
height: this.$store.state.chartStyleObject.height,
marginTop: this.$store.state.chartStyleObject.marginTop,
marginRight: this.$store.state.chartStyleObject.marginRight,
marginBottom: this.$store.state.chartStyleObject.marginBottom,
marginLeft: this.$store.state.chartStyleObject.marginLeft,
};
},
},
}

How to change size of Toggle Switch in Material UI

This is my first time using Material UI (I'm also a noob with react in general) and I cant seem to change the size of the toggle switch I'm using.
This is what I have so far -minus all the non related stuff:
import React, { Component } from "react";
import Switch from "#material-ui/core/Switch";
const styles = {
root: {
height: "500",
},
};
class ToggleActive extends Component {
state = {
checked: true,
};
handleChange = name => event => {
this.setState({ [name]: event.target.checked });
};
render() {
return (
<label htmlFor="normal-switch">
<Switch
classes={styles.root}
checked={this.state.checked}
onChange={this.handleChange("checked")}
/>
</label>
);
}
}
export default ToggleActive;
I just want to make it a bit larger, and change the color. Any help would be appreciated!
The change in the Switch component requires a little bit of detailed styling. I added some comments in parts that are not very obvious:
import {createStyles, makeStyles, Switch, Theme} from '#material-ui/core';
const useStyles = makeStyles((theme: Theme) =>
createStyles({
root: {
width: 54,
height: 40,
padding: 0,
margin: theme.spacing(1),
},
switchBase: {
padding: 1,
'&$checked': {
// This is the part that animates the thumb when the switch is toggled (to the right)
transform: 'translateX(16px)',
// This is the thumb color
color: theme.palette.common.white,
'& + $track': {
// This is the track's background color (in this example, the iOS green)
backgroundColor: '#52d869',
opacity: 1,
border: 'none',
},
},
},
thumb: {
width: 36,
height: 36,
},
track: {
borderRadius: 19,
border: `1px solid ${theme.palette.grey[300]}`,
// This is the background color when the switch is off
backgroundColor: theme.palette.grey[200],
height: 30,
opacity: 1,
marginTop: 4,
transition: theme.transitions.create(['background-color', 'border']),
},
checked: {},
focusVisible: {},
})
);
You can implement this as a functional component:
import React, { useState } from 'react';
// import {createStyles, makeStyles, ...
// const useStyles = makeStyles((theme: Theme) => ...
export const ToggleItem: React.FC = () => {
const styles = useStyles();
const [toggle, setToggle] = useState<boolean>(false);
return (
<Switch
classes={{
root: styles.root,
switchBase: styles.switchBase,
thumb: styles.thumb,
track: styles.track,
checked: styles.checked,
}}
checked={toggle}
onChange={() => setToggle(!toggle)}
name={title}
inputProps={{'aria-label': 'my toggle'}}
/>
);
};
This is now even easier to accomplish because MUI has an official example in the documentation:
https://mui.com/material-ui/react-switch/#customization
Using that as an example, the minimum number of changes to accomplish making the switch bigger is actually just this:
export const MuiSwitchLarge = styled(Switch)(({ theme }) => ({
width: 68,
height: 34,
padding: 7,
"& .MuiSwitch-switchBase": {
margin: 1,
padding: 0,
transform: "translateX(6px)",
"&.Mui-checked": {
transform: "translateX(30px)",
},
},
"& .MuiSwitch-thumb": {
width: 32,
height: 32,
},
"& .MuiSwitch-track": {
borderRadius: 20 / 2,
},
}));
Here is the link to a forked sandbox with just a bigger switch:
https://codesandbox.io/s/customizedswitches-material-demo-forked-4m2t71
Consider this: I am not a front-end developer and did not develop in
Material-UI framework for years now. so just look for a different answer or send
me an edit version which works.
For changing the size of the switch component you should use size props that can be in two size 'small' || 'medium'.For example:
<Switch
size="small"
checked={this.state.checked}
onChange={this.handleChange("checked")}
color='primary'
/>
If it doesn't work for you then You need to change CSS style at root class:
const styles = {
root: {
height: 500,
width: 200},
};
Due to material-UI component API for changing the color of a switch you need to add a color props into you Switch JSX tag and choose from these enum:
enum: 'primary' |'secondary' | 'default'
your Switch should be like this:
<Switch
classes={styles.root}
checked={this.state.checked}
onChange={this.handleChange("checked")}
color='primary'
/>
Material-UI for switch size prop

Pop up alert when input is empty in react

I have asked this question many times here but didn't get the answer properly or any complete result. i need to validate my input or i can do that when my input tag is empty or when there is no number in the input, the alert should pop up. I tried for an alert but don't know why it is not working. Please help i'm stuck in this since a week.
Code:
<script type="text/jsx">
var styles = {
margin: '2em auto',
width: '300px',
height: '300px',
backgroundColor: '#DD4814',
color: '#ffffff',
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'space-around'
};
var inputs = {
position: 'relative',
bottom: '17%',
left: '20%'
}
var btns = {
position: 'relative',
bottom: '7%'
}
var btn = {
backgroundColor: '#ffffff',
color: '#000000',
borderColor: '#DEB887',
borderRadius: '0.4em',
cursor: 'pointer',
margin: '0 1em',
padding: '0.5em',
display: 'inline-block'
}
var required = true;
class Timer extends React.Component {
constructor (props) {
super(props)
this.state = {count: 0, customNumber: 0}
}
handleChange (e) {
this.setState({ customNumber: e.target.value});
}
componentWillUnmount () {
clearInterval(this.timer)
}
tick () {
if (this.state.customNumber) {
this.setState({
count: (this.state.customNumber--)
})
if (this.state.customNumber <= 0) {
this.setState({ count: 0})
clearInterval(this.timer)
this.setState({ disabled: false })
}
} else {
this.setState({count: (this.state.count - 1)})
}
}
display () {
return ('0' + this.state.count % 100).slice(-2)
}
startTimer () {
if ((this.state.inputValue == " ") && isNaN(this.state.inputValue))
{
alert("Please give some value in number");
}
clearInterval(this.timer)
this.timer = setInterval(this.tick.bind(this), 1000)
this.setState({ disabled: true })
}
stopTimer () {
clearInterval(this.timer)
}
resetTimer () {
clearInterval(this.timer)
this.setState({count: 0})
this.setState({ disabled: false })
}
render () {
return (
<div style={styles} className='timer'>
<h1 style={{fontSize: '4em'}}>{this.display()}</h1>
<div className="input_text" style={inputs}>
<label htmlFor="custom_number">Enter number to start timer</label>
<input type="text" name="custom_number" id="custom_number" required={required} value={this.state.inputValue} onChange={this.handleChange.bind(this)} disabled={this.state.disabled} placeholder="Enter b/w 1-100" />
</div>
<div style={btns} className="buttons">
<button style={btn} type="button" name="start_btn" id="start_btn" onClick={this.startTimer.bind(this)}>Start</button>
<button style={btn} type="button" name="stop_btn" id="stop_btn" onClick={this.stopTimer.bind(this)}>Pause</button>
<button style={btn} type="button" name="reset_btn" id="reset_btn" onClick={this.resetTimer.bind(this)}>Stop</button>
</div>
</div>
)
}
}
ReactDOM.render(
<Timer />,
document.getElementById('root')
)
</script>
<div id="root"></div>
First thing, using alerts is not the best way to get the user's attention. console.log() is much more effective if all you are doing is debugging your code
Second thing, you are asking for alerts in a timer loop - you could end up with hundreds of alerts this way (refer to my first point)
Third thing, you are checking the value of this.state.inputValue and comparing it to a string containing one space (" ") which doesn't seem right
Fourth thing, you are setting the value of your input field with this:
value={this.state.inputValue}
This basically means the value of the field is set and can't be changed. You probably want to use defaultValue instead
Five, and I'm stopping here, your handleChange method doesn't even set the state, so you will never get what you want anyway.

Shoutem change default fontFamily not work

im newbie in react native! I'm used shoutem/ui in my project.
I have problem when modify default fontFamily. here is my code, please check then help me some solution to handle this.
thanks so much guys.
const theme = _.merge(getTheme(), {
defaultFont: {
fontFamily: 'Rubik-Italic',
},
'shoutem.ui.NavigationBar': {
'.clear': {
container: {
backgroundColor: params.primaryColor,
borderBottomColor: 'transparent',
position: 'relative',
},
'shoutem.ui.Title': {
color: 'white',
fontSize: 16,
},
},
'.normal': {
container: {
position: 'relative'
},
'shoutem.ui.Button': {
'shoutem.ui.Icon': {
color: params.colorTextAlpha,
},
'shoutem.ui.Text': {
color: params.colorTextAlpha,
},
},
'shoutem.ui.Title': {
color: params.colorText,
},
}
},
'shoutem.ui.Row': {
'.fix': {
paddingHorizontal: 10,
paddingVertical: 10,
}
}
});
What you want to do is override the theme variables.
Import the default theme variables and the getTheme function:
import {
getTheme,
defaultThemeVariables,
} from '#shoutem/ui';
Then define your custom variables:
const myThemeVariables = {
...defaultThemeVariables,
title: { fontFamily: 'MyFont' },
};
And then define your custom theme that uses those variables:
const myTheme = getTheme(myThemeVariables);
There is no more defaultFont setting you can override, so you'll have to be specific unfortunately.
Furthermore, you have to import the StyleProvider:
import { StyleProvider } from '#shoutem/theme';
And use it to control the style of your components:
render() {
return (
<StyleProvider style={myTheme}>
// your components here
</StyleProvider>
);
}
}

Change color of react-big-calendar events

I need to make a calendar with events and I decided to use react-big-calendar. But I need to make events of different colors. So each event will have some category and each category has corresponding color. How can I change the color of the event with react?
Result should look something like this
Sorry, I haven't read the documentation really well. It can be done with the help of eventPropGetter attribute. I've made it like this:
eventStyleGetter: function(event, start, end, isSelected) {
console.log(event);
var backgroundColor = '#' + event.hexColor;
var style = {
backgroundColor: backgroundColor,
borderRadius: '0px',
opacity: 0.8,
color: 'black',
border: '0px',
display: 'block'
};
return {
style: style
};
},
render: function () {
return (
<Layout active="plan" title="Planning">
<div className="content-app fixed-header">
<div className="app-body">
<div className="box">
<BigCalendar
events={this.events}
defaultDate={new Date()}
defaultView='week'
views={[]}
onSelectSlot={(this.slotSelected)}
onSelectEvent={(this.eventSelected)}
eventPropGetter={(this.eventStyleGetter)}
/>
</div>
</div>
</div>
</Layout>
);
}
Additional tip on how to style different kinds of events: In the myEvents array of event objects, I gave each object a boolean property isMine, then I defined:
<BigCalendar
// other props here
eventPropGetter={
(event, start, end, isSelected) => {
let newStyle = {
backgroundColor: "lightgrey",
color: 'black',
borderRadius: "0px",
border: "none"
};
if (event.isMine){
newStyle.backgroundColor = "lightgreen"
}
return {
className: "",
style: newStyle
};
}
}
/>
This solution is simple !
eventPropGetter={(event) => {
const backgroundColor = event.allday ? 'yellow' : 'blue';
return { style: { backgroundColor } }
}}
change the condition according to your need and it is done.
Siva Surya's solution is the fastest, and I have added the color property as well. Thanks...
import React, {useEffect, useLayoutEffect} from 'react';
import { Calendar, momentLocalizer,globalizeLocalizer } from 'react-big-calendar'
import moment from 'moment';
import { connect } from 'frontity';
import BackgroundWrapper from 'react-big-calendar/lib/BackgroundWrapper';
const MyCalendar = ({ actions, state, objetoBloque, formato }) => {
const localizer = momentLocalizer(moment);
const myEventsList = [
{
title: 'My Event',
start: '2022-06-21T13:45:00-05:00',
end: '2022-06-25T14:00:00-05:00',
// elcolor:'red'
colorEvento:'red'
},
{
title: 'Otro',
start: '2022-06-15T13:45:00-05:00',
end: '2022-06-23T14:00:00-05:00',
colorEvento:'green',
color:'white'
}
];
return(
<div>
<Calendar
// defaultDate = {defaultDate}
localizer={localizer}
events={myEventsList}
startAccessor="start"
endAccessor="end"
style={{ height: 500 }}
BackgroundWrapper = "red"
eventPropGetter={(myEventsList) => {
const backgroundColor = myEventsList.colorEvento ? myEventsList.colorEvento : 'blue';
const color = myEventsList.color ? myEventsList.color : 'blue';
return { style: { backgroundColor ,color} }
}}
/>
</div>
)
}
export default connect(MyCalendar);
Searching for how to change the border colour of an event also lead me here, and I couldn't find the answer anywhere else, but found that adding the following done the trick:
border: "black",
borderStyle: "solid"

Categories