Using the Same Onclick Button Increment Counter Up to 2 (Range 0-2) and Then Decrement Back to 0 from 2

using the same onClick button increment counter up to 2 (range 0-2) and then decrement back to 0 from 2

With just count, there is no logical way to determine increment or decrement. You can add a boolean in state track increment vs decrement.

onClick(e) {
let count = this.state.increment ? this.state.count + 1 : this.state.count - 1;

let increment = this.state.increment;

if (count === 0) {
increment = true;
} else if (count >= 2) {
increment = false;
}

this.setState({
count,
increment,
});
}

https://jsfiddle.net/69z2wepo/264102/

Increment / Decrement function in ReactJS

You could set a conditional in the function you trigger when you click on the button. Maybe something like this:

import React, { Component } from 'react';

class App extends Component {
constructor(props) {
super(props);
this.state = {
counter: 0,
clicked: false,
};
}

toggleClicked = () => {
const counter = this.state.clicked ? counter +1 : counter - 1;
const clicked = !this.state.clicked;

this.setState({ counter, clicked })
}

render() {
return (
<div>
<button onClick={this.toggleClicked}>Click</button>

{ this.state.counter ? <h2>{ this.state.counter }</h2> : '' }
</div>
);
}
}

export default App;

This way if you have already clicked the counter will decrease by 1 and viceversa.

Why is useReducer setup in this way? It feels like it's writing the code backwards?

useReducer returns an array whose first value is the state and the second value is the dispatch. You are de-structuring these values.

const someArray = () => ['value1','value2']
const [value1 , value2] = someArray()
console.log(value1)
console.log(value2)

High frequency counter in Reactjs

If you need something with that high a frequency, just look at the system time and the time you start counting at, á la

const counterPosition = ((+new Date() - startTime) * 100000) % 100000;

Here's an example - a frequency of 100,000 may prove difficult due to the inaccuracy of new Date()...

// TODO: this useRequestAnimationFrame implementation could be buggy;
// it is here only to have CounterApp get updated "as fast as it can".
function useRequestAnimationFrame() {
const [num, setNum] = React.useState(0);
const keepUpdatingRef = React.useRef(true);
React.useEffect(() => {
const requestNext = () => {
if(keepUpdatingRef.current) requestAnimationFrame(update);
};
const update = () => {
setNum(n => n+1);
requestNext();
};
requestNext();
return () => keepUpdatingRef.current = false;
}, []);
return num;
}


function CounterApp({frequency}) {
const frame = useRequestAnimationFrame();
const [startTime] = React.useState(() => +new Date());
const elapsed = (+new Date() - startTime) / 1000.0;
const counter = Math.floor((elapsed * frequency) % frequency);
return <div>{counter}</div>;
}

ReactDOM.render(<CounterApp frequency={100} />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.0/umd/react-dom.production.min.js"></script>
<div id="root"></div>

Enzyme still finding element that should be hidden by conditional rendering in React

Try this way,

const setup = () => shallow(<App />);
const findByTestAttr = (wrapper, val) => wrapper.find(`[data-test='${val}']`);

test('error message disappears when counter larger than 0', () => {
const wrapper = setup();

//Decrement opration
const decrementButton = findByTestAttr(wrapper, 'decrement-button');
decrementButton.simulate('click');
let errorMessage = findByTestAttr(wrapper, 'below-zero-error-message');
console.log('Error ==>',wrapper.debug());
expect(errorMessage.length).toBe(1);

// Increment Operation
const incrementButton = findByTestAttr(wrapper, 'increment-button');
incrementButton.simulate('click');
console.log('No error ==>',wrapper.debug());
errorMessage = findByTestAttr(wrapper, 'below-zero-error-message');
expect(errorMessage.length).toBe(0);
});

Let me know if you are facing any issues.

Continuously increase integer value as the button is pressed

For that to work, you need a thread that will update the integer value when you long press on a button.

Create a handler in your activity:

private Handler repeatUpdateHandler = new Handler();

And 2 vars which will state: is it increment or decrement? Only one set at a time.

private boolean mAutoIncrement = false;
private boolean mAutoDecrement = false;

And the present number value

public int mValue;

And a class that will run in another thread:

class RptUpdater implements Runnable {
public void run() {
if( mAutoIncrement ){
increment();
repeatUpdateHandler.postDelayed( new RptUpdater(), REP_DELAY );
} else if( mAutoDecrement ){
decrement();
repeatUpdateHandler.postDelayed( new RptUpdater(), REP_DELAY );
}
}
}

Add a long press listener to your button:

mBTIncrement.setOnLongClickListener( 
new View.OnLongClickListener(){
public boolean onLongClick(View arg0) {
mAutoIncrement = true;
repeatUpdateHandler.post( new RptUpdater() );
return false;
}
}
);

mBTIncrement.setOnTouchListener( new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
if( (event.getAction()==MotionEvent.ACTION_UP || event.getAction()==MotionEvent.ACTION_CANCEL)
&& mAutoIncrement ){
mAutoIncrement = false;
}
return false;
}
});

In the above case the button is the increment one. Create another button which will set mAutoDecrement to true.

And decrement() will be a function, which will set your instance int variable like this:

public void decrement(){
mValue--;
_value.setText( ""+mValue );
}

You figure the increment out. Oh and REP_DELAY is a static int variable set to 50.

I see this is an excerpt from Jeffrey Cole's open source NumberPicker available at http://www.technologichron.net/ Proper author's attribution must be added.



Related Topics



Leave a reply



Submit