Reputation: 107
Okay, So The code for my alphabetic buttons in my Hangman game works well, it shows up on the page in the guessed letter section when clicked and if the letter is correct it is appended to and replaces the underscore in the right place (_ _ _ _) My question is: How can I refactor my handleClick(event) in a way that when the button is clicked the button disappears (so maybe by adding a class, set display:none)
export class Input extends Component {
handleClick = (event) => {
if (this.props.guesses.includes(event.target.value)) {
return this.event.value
} else {
return this.props.makeGuess(event.target.value.toLowerCase())
}
}
render() {
const alphabet = [...'ABCDEFGHIJKLMNOPQRSTUVWXYZ'];
return (<div className="containerAlph">
{alphabet.map((letter, index) => <button className="AlphaBet" key={index} onClick={this.handleClick} value={letter}>{letter}</button>)}
</div>);
}
}
Upvotes: 0
Views: 1054
Reputation: 7460
There are many ways to do this.
I am going to use the state to do so instead of adding a CSS class. Basically you will keep track of the buttons available through the alphabet
array. Each time we click on a button, we will remove that letter from the array and re-render the component.
First of all, I would change your alphabet
array to be a state property. That way every time you update it, it will be re-rendered and your buttons will disappear accordingly.
So first change, in your render function let us change the alphabet
to come from the state:
const { alphabet } = this.state
I declared this in the component's constructor:
constructor (props) {
super(props)
this.state = {
alphabet : [...'ABCDEFGHIJKLMNOPQRSTUVWXYZ']
}
}
Now... lets deal with the handleClick
function. We want to pass in which letter we are clicking, and remove that letter from the alphabet
array.
In the return statement when rendering the buttons, make sure to pass in which letter you are removing in the handleClick
function.
return (<div className="containerAlph">
{alphabet.map((letter, index) => <button className="AlphaBet" key={index} onClick={() => this.handleClick(letter)} value={letter}>{letter}</button>)}
</div>);
Now for the function itself: Grab the value of alphabet state, and remove the letter you clicked on from that state.
this.setState
causes the component to re-render, and now that you removed the letter you clicked on, it won't be displayed anymore.
handleClick(letter) {
const alphabet = [...this.state.alphabet]
// remove the letter from the state
const index = alphabet.indexOf(letter)
if (index > -1) {
alphabet.splice(index, 1);
}
this.setState({ alphabet })
}
Hope that helps.
Here is a working app:
class App extends React.Component {
constructor (props) {
super(props)
// set the state alphabet as your array so that
// we can re-render whenever we update it
this.state = {
alphabet : [...'ABCDEFGHIJKLMNOPQRSTUVWXYZ']
}
}
handleClick(letter) {
const alphabet = [...this.state.alphabet]
// remove the letter from the state
const index = alphabet.indexOf(letter)
if (index > -1) {
alphabet.splice(index, 1);
}
this.setState({ alphabet })
}
render() {
const { alphabet } = this.state
return (<div className="containerAlph">
{alphabet.map((letter, index) => <button className="AlphaBet" key={index} onClick={() => this.handleClick(letter)} value={letter}>{letter}</button>)}
</div>);
}
}
ReactDOM.render(
<App />,
document.getElementById('app')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>
Update: as mentioned in the conversation, here is how I think your handleClick
should be to incorporate the other stuff you would like to happen:
handleClick = (event, letter) => {
// First do the stuff to make the button disappear
const alphabet = [...this.state.alphabet]
const index = alphabet.indexOf(letter)
if (index > -1) {
alphabet.splice(index, 1);
}
this.setState({ alphabet })
// now do the other stuff
if (this.props.guesses.includes(event.target.value)) {
return this.event.value
} else {
return this.props.makeGuess(event.target.value.toLowerCase())
}
}
Now in the render function, we just need to pass in both parameters:
render() {
const { alphabet } = this.state
return (<div className="containerAlph">
{alphabet.map((letter, index) => <button className="AlphaBet" key={index} onClick={(event) => this.handleClick(event, letter)} value={letter}>{letter}</button>)}
</div>);
}
Upvotes: 2