How to get button's index - javascript

I used to make bunch of buttons through for-looping.
title[] has a lot of values.
export const renderButtons1 = (numOfBtns,title,navigate) => {
const views1 = [];
for ( var i = 0; i < numOfBtns; i++) {
views1.push(
<Button
key={i}
title = {title[i]}
onPress={() => navigate('List', {
Title : title[i]
})}
color="#841584"
/>);
}
return views1;
}
in EventListscreen, Title: title[i] does not work, i value is not recognized
the one I want to ask is when I click first button, index 0 will be retrieved.
I thought I can use button key, but it is not fixed value - when I click first button at first and at second time, it is different..

I found the way,
you guys need to make the function for making buttons
so it looks like this
export const makingbutton = (i,ttl,navigate) => {
return <Button
key={i}
title = {ttl[i]}
onPress={() => navigate('List', {
Title : title[i]
})}
color="#841584"
/>
}
export const renderButtons1 = (numOfBtns,title,navigate) => {
const views1 = [];
for ( var i = 0; i < numOfBtns; i++) {
views1.push(
makingbutton(i,title,navigate)
);
}
return views1;
}

Related

Making Answer button render with random indexes

Is there a way to make the correct button hard coded in the Question component render between the mapped incorrect buttons to prevent the correct answer from always being the first button rendered with every question? Or a way to map through both correct and incorrect answers to display the answers with random positions, the question array comes from the API in this form:
{
question: "The words and originate from the languages of which country?",
correctAnswer: "India",
incorrectAnswers: ["Papua New Guinea", "Ethiopia", "China"]
}
const [request, setRequest] = React.useState([])
React.useEffect (() => {
fetch('https://opentdb.com/api.php?amount=5')
.then(res => res.json())
.then(data => setRequest(data.results.map(({ question, correct_answer, incorrect_answers }) => ({question, correct_answer, incorrect_answers}))))
}, [])
console.log(request)
const questionElements = request.map(req => {
return (
<Question
question = {req.question}
correct_answer ={req.correct_answer}
incorrect_answers = {req.incorrect_answers}
scoreFunction = {scoreFunction}
// disabled = {disable}
/>
)
})
// Question Component
const incorrectAnswers = props.incorrect_answers.map(ans => {
return (
<button className ="button">{ans}</button>
)
})
return(
<div className = "question-div">
<h1 className = "question">{props.question}</h1>
<div className = "answerBlock">
<button
disabled = {disable}
className ="button correct"
onClick = {() => {
props.scoreFunction()
setDisable(true)}}>{props.correct_answer} </button>
{incorrectAnswers}
</div>
<hr />
</div>
)
You can put all answers to the same array, sort data inside it and then generate buttons.
This shows a simple shuffle function for arrays:
How to randomize (shuffle) a JavaScript array?
Example:
const correct_answer = 'correct'
const incorrect_answers = ['incorrect 1','incorrect 2','incorrect 3']
function shuffle(array) {
let currentIndex = array.length, randomIndex;
// While there remain elements to shuffle.
while (currentIndex != 0) {
// Pick a remaining element.
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex--;
// And swap it with the current element.
[array[currentIndex], array[randomIndex]] = [
array[randomIndex], array[currentIndex]];
}
return array;
}
const all_answers = shuffle([correct_answer, ...incorrect_answers])
console.log(all_answers)
So your code should look like this:
const [request, setRequest] = React.useState([])
React.useEffect (() => {
fetch('https://opentdb.com/api.php?amount=5')
.then(res => res.json())
.then(data => setRequest(data.results.map(({ question, correct_answer, incorrect_answers }) => ({question, correct_answer, incorrect_answers, all_answers: [correct_answer, ...incorrect_answers]}))))
}, [])
function shuffle(array) {
let currentIndex = array.length, randomIndex;
// While there remain elements to shuffle.
while (currentIndex != 0) {
// Pick a remaining element.
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex--;
// And swap it with the current element.
[array[currentIndex], array[randomIndex]] = [
array[randomIndex], array[currentIndex]];
}
return array;
}
console.log(request)
const questionElements = request.map(req => {
return (
<Question
question = {req.question}
correct_answer ={req.correct_answer}
incorrect_answers = {req.incorrect_answers}
scoreFunction = {scoreFunction}
// disabled = {disable}
/>
)
})
// Question Component
const allAnswers = shuffle(props.all_answers).map(ans => {
if(ans !== props.correct_answer) {
return (
<button className ="button">{ans}</button>
)
}
return (
<button
disabled = {disable}
className ="button correct"
onClick = {() => {
props.scoreFunction()
setDisable(true)}}
>{props.ans}</button>
)
})
return(
<div className = "question-div">
<h1 className = "question">{props.question}</h1>
<div className = "answerBlock">{allAnswers }</div>
<hr />
</div>
)
How about something like this?
function getRandomArbitrary(min, max) {
return Math.random() * (max - min) + min;
}
const incorrect_answers_count = props.incorrect_answers.length;
const correct_answer_random_index = getRandomArbitrary(1, incorrect_answers_count) - 1;
const combined_answers = props.incorrect_answers.splice(correct_answer_random_index, 0, props.correct_answer);
const answers = combined_answers.map((ans, index) => {
return (
<button key={"answer-button-" + index} className ="button">{ans}</button>
)
})
Not sure why you want to have the correct button different, because the user can actually see this in the browser. But if you do, you can predefined the buttons and only then do the mapping.

React js: Uncaught Error: Objects are not valid as a React child [duplicate]

This question already has answers here:
When should I use a return statement in ES6 arrow functions
(6 answers)
Closed 11 months ago.
I am trying to display my data from an array. The array comes from a reducer. I wanted to do it using the .map method but there is an error (at produit.map). I don't know why but it returns me "Uncaught Error: Objects are not valid as a React child". The console tell me too that they found Objects with keys. Can someone help me please?
const LastProduit = () => {
const dispatch = useDispatch();
const step = 3;
const [count, setCount] = useState(step);
useEffect(() => {
dispatch(getProduit());
}, [dispatch,]);
const { height, width } = useWindowDimensions();
const produits = useSelector((state) => state.produitReducer);
const produitsArray = produits;
const RealProduitArray = produitsArray[0];
console.log(produits);
console.log(RealProduitArray);
//console.log(RealProduitArray[0].titre);
const a = [produits];
const b = 1 + produits.length
for (let i = 0; i < b; i++) {
return a[i];
}
let screenwidth = { width };
let nbr = 0;
let nbrspace = 0;
let valeur = "true";
console.log(screenwidth.width);
if (screenwidth.width <= 768) { nbr = 2; nbrspace = -60; valeur = "false" }
else { nbr = 4; nbrspace = -170; }
return (
<div className='LastProduit'>
<p className='categories_titre'>Derniers Produits </p>
<div className='LastProduit_img'>
<Swiper modules={[Navigation, Pagination, Scrollbar, A11y]}
spaceBetween={nbrspace}
slidesPerView={nbr}
navigation
pagination={{ clickable: true }}
scrollbar={{ draggable: true }}
onSwiper={(swiper) => console.log(swiper)}
onSlideChange={() => console.log('slide change')}
>
{produits.map((produit) =>
<SwiperSlide>
<Produit produit={produit} key={produit._id} />
</SwiperSlide>
)}
</Swiper>
</div>
</div>
);
};
Your map function needs a return statement. In multi-line callback functions you have to include the return keyword.
Example:
{
produits.map((produit) => {
return (
<SwiperSlide>
<Produit produit={produit} key={produit._id} />
</SwiperSlide>
)
})
}

In Svelte, is there a way to undo invalid user input, without changing the state?

In Svelte, is there a way to undo invalid user input, without triggering a momentarily fake property change for state?
For example (try it online), when user types in 123a in the input box, I want to covert it to a number and assign it counter.
For that, I have to introduce a temporary and redundant change to counter (using Number.NaN below). Otherwise, counter won't change, and 123a will remain inside the input box, while I want to revert it back to 123:
<script>
let count = 0;
const handleClick = () => count++;
const handleChange = async e => {
const userValue = e.target.value;
let newValue = userValue? parseInt(userValue): 0;
if (isNaN(newValue)) newValue = count;
count = Number.NaN;
await Promise.resolve();
count = newValue;
};
</script>
Count: <button on:click={handleClick}>{count}</button>
<br />
A: <input value={count} on:input={handleChange} />
<br />
Is there a better way of doing it? Essentially, I want trigger a manual re-render for a part of my Svetle component, without changing the state.
Of course, in the event handler I could undo the change just by modifying e.target.value directly:
const handleChange = async e => {
const userValue = e.target.value;
let newValue = userValue? parseInt(userValue): 0;
if (isNaN(newValue)) newValue = count;
if (newValue == count)
e.target.value = count;
else
count = newValue;
};
But I wonder if there's a way to tell Svelte to re-render the whole <input>?
To compare, here's how I could do it in React (try it online):
function App() {
let [count, setCount] = useState(0);
const handleClick = () => setCount((count) => count + 1);
const handleChange = (e) => {
const userValue = e.target.value;
let newValue = userValue ? parseInt(userValue) : 0;
if (isNaN(newValue)) newValue = count;
setCount(newValue);
};
return (
<>
Count: <button onClick={handleClick}>{count}</button>
<br />
A: <input value={count} onInput={handleChange} />
<br />
</>
);
}
You simply need to bind count to the value of the input. REPL
<script>
let count = 0;
const handleClick = () => count++;
const handleChange = (e) => {
const userValue = e.target.value;
const newValue = userValue ? parseInt(userValue, 10) : 0;
count = isNaN(newValue) ? count : newValue;
};
</script>
Count: <button on:click={handleClick}>{count}</button>
<br />
A: <input bind:value={count} on:input={handleChange} />
<br />
Note: Remember to always pass a radix to parseInt(), it does not default to 10.

How can I use a ref to change class name of the element I have clicked?

I want to make refs that reference each cell in the graph. Doing the usual way, I only get the reference to the last cell created in the graph.
I have the details below:
How I am generating the grid:
class Grid {
getInitialGrid() {
const grid = [];
for (let row = 0; row < row_size; row++) {
const currentRow = [];
for (let col = 0; col < col_size; col++) {
currentRow.push(this.createNode(col, row));
}
grid.push(currentRow);
}
return grid;
};
createNode(col, row) {
return {
col,
row,
};
};
}
The .jsx file that I have. I have indicated the place where the ref should be
<div
className="table"
>
{grid.map((row, index) => {
return (
<div key={index}
>
{row.map((node) => {
return ( // each node
<div key={col}
//this is where I want to use the ref
id={`${row}-${col}`}
className={`cell ${this.classNameFunc(begNode, endNode, wallNode, isVisited)}`}
onMouseDown={() => this.mouseTest(row, col)}
>
</div>
);
})}
</div>
);
})}
</div>

How to add attribute name and attribute value dynamically in React

I want to set value="a" depending on the condition it meets. Button has no value attribute currently. How do I write this?I want like this <button value="a"> One </button>
const buttonValues = ["a", "b"]
const addingValuesToButtons = () => {
for (var i = 0; i < buttonValues.length; i++) {
if(buttonValues[i] === "a") {
//add attribute name and value to first two buttons
}
if(buttonValues[i] === "b"){
//add attribute name and value to first three buttons
}
};
return(
<div>
<button> One </button>
<button> Two </button>
<button> Three </button>
<button> Four </button>
</div>
)
}
const buttonValues = ["a", "b"]
const addingValuesToButtons = () => {
const buttons = [];
for (var i = 0; i < buttonValues.length; i++) {
if(buttonValues[i] === "a") {
buttons.push({attr: 'foo', name: 'bar'});
}
if(buttonValues[i] === "b"){
buttons.push({attr: 'baz', name: 'bar2'})
}
};
return(
<div>
{buttons.map(button => {
return <button attr={button.attr}>{button.name}</button>;
})}
</div>
)
}
It will go like this:
<button value={this.buttonValues[0] == 'a'?this.buttonValues[0]:null}> One </button>
another netter approach is :
const buttonValues = [{value:"a",name:"One"}, {value:"b",name:"two"}]
this.buttonValues.map(value => {<button value={value.value == 'a'? value.value:null}>{value.name}</button>}) ;

Categories

Resources