Reputation: 129
I've made a "ToDo" sort of small project, but instead its a list of names. I type a name in and add it to the array. Then I can also delete each item.
Now I want to press a button that randomly chooses one of the items/names within in the array and displays the name. I'm really struggling to figure out how to write the code for this (I'm new to TypeScript).
I can console.log a random name at a time by using the state.
Console.log random name from array
<button onClick={() => console.log((this.state.names[Math.floor(Math.random() * this.state.names.length)]))}>Add name</button>
NameList.tsx
import * as React from 'react';
import {RouteComponentProps} from "react-router-dom";
interface IState {
currentName: string;
names: Array<IList>
}
interface IList {
id: number,
value: string,
}
export default class List extends React.Component<RouteComponentProps, IState> {
constructor(props: RouteComponentProps) {
super(props);
this.state = {
currentName: "",
names: []
}
}
public handleSubmit(e: React.FormEvent<HTMLFormElement>): void {
e.preventDefault();
this.setState({
currentName: "",
names: [
...this.state.names,
{
id: this._timeInMilliseconds(),
value: this.state.currentName,
}
]
})
}
public onChange(e: any): void {
this.setState({
currentName: e.target.value
})
}
public removeUser(id: number): void {
const filteredTasks: Array<IList> = this.state.names.filter((task: IList) => task.id !== id);
this.setState({
names: filteredTasks
});
}
public renderList(): JSX.Element[] {
return this.state.names.map((task: IList, index: number) => {
return (
<div key={task.id} className="user">
<span className={task.completed ? "is-completed" : ""}>{task.value}</span>
<button onClick={() => this.removeUser(task.id)}> Delete </button>
</div>
)
});
}
public render(): JSX.Element {
return (
<div className={"header col-lg-12 form-wrapper"}>
<h1> Add names to the list </h1>
<div className="alert alert-info" role="alert">
<p>Press the button to select a random name from the list</p>
<button>Get random name</button>
<section>
{this.renderList()[Math.floor(Math.random() * this.state.names.length)]}
</section>
</div>
<form onSubmit={(e) => this.handleSubmit(e)}>
<input type="text" className="tdl-input" placeholder="Add a name to the list"
value={this.state.currentName}
onChange={(e) => this.onChange(e)}
/>
<button type="submit">Add name</button>
</form>
<section>
{this.renderList()}
</section>
</div>
);
}
private _timeInMilliseconds(): number {
const date: Date = new Date();
return date.getTime();
}
}
Hope someone can guide me in the right direction - I believe I need to make a function that takes the array and gets a random value, but I don't know which array function to use to do this.
Additionally, I'm trying to get the random name to never show twice in a row - I believe I need to store the value in a new array somehow, unsure though.
Upvotes: 1
Views: 2093
Reputation: 11001
Add one state variable randomIndex
this.state = {
currentName: "",
randomIndex: 0,
names: []
}
Have a method to set random index
public setRandomIndex(): void {
const randomIndex: number = Math.floor(Math.random() * this.state.names.length);
this.setState({
randomIndex
});
}
button
and section
. Use randomIndex
and display item from array. <button onClick={() => this.setRandomIndex()}>Get random name</button>
<section>
{this.renderList()[this.state.randomIndex]}
</section>
Update:
Adding way to avoid having same random index.
1) use the setRandomIndex2
method instead of setRandomIndex
2) Initialise the state variable randomList: []
in constructor.
Basically maintain random index list, add to this only when not repeat and make sure to reset list when the size reaches to same as name list
.
public setRandomIndex2(): void {
let randomList = this.state.randomList;
if (randomList.length === this.state.names.length) {
randomList = [];
}
let randomIndex: number = Math.floor(Math.random() * this.state.names.length);
while (randomList.includes(randomIndex)) {
randomIndex = Math.floor(Math.random() * this.state.names.length);
}
randomList.push(randomIndex);
this.setState({
randomList,
randomIndex
});
}
Upvotes: 2