How to style each element individually based on their boolean property? - javascript

I have DATA array in which i store objects that contain sentences and answers. Each answer has its isCorrect prop.
How do I check answer correctnes on button click?
After button click, correct answers should make <select> tag border change to green and incorrect or undefined to red.
Parent component:
export default function App() {
const [isCorrect, setIsCorrect] = useState();
const [isChecked, setIsChecked] = useState(false);
const handleValueChange = (isCorrect) => {
setIsCorrect(isCorrect);
};
return (
<Wrapper>
{DATA.map((sentence, index) => (
<Sentence isCorrect={isChecked ? isCorrect : null}>
<span>
{index + 1}. {sentence.sentenceFirstPart}
</span>
<select>
{sentence.answerOptions.map((option) => (
<option
onChange={() => handleValueChange(option.answerText)}
value={option.answerText}
>
{option.answerText}
</option>
))}
</select>
<span>{sentence.sentenceSecondPart}</span>
</Sentence>
))}
<button onClick={() => setIsChecked(true)}>Check</button>
</Wrapper>
);
}
Styled components:
const Wrapper = styled.div`
display: flex;
flex-direction: column;
gap: 1rem;
button {
padding: 0rem 1rem;
width: 6rem;
}
`;
export const Sentence = styled.div`
display: flex;
align-items: center;
span {
font-size: 1.2rem;
}
select {
margin: 0 0.5rem;
border: 1px solid;
padding: 0.2rem;
border-radius: 4px;
font-weight: 500;
border-color: ${({ isCorrect }) =>
isCorrect ? "green" : !isCorrect && isCorrect !== undefined ? "red" : ""};
}
`;
Test data:
const DATA = [
{
sentenceFirstPart: "It takes a lot of",
sentenceSecondPart: "to learn how to waterski properly",
answerOptions: [
{ answerText: "", isCorrect: false },
{ answerText: "attempt", isCorrect: false },
{ answerText: "effort", isCorrect: true },
{ answerText: "trial", isCorrect: false },
{ answerText: "try", isCorrect: false }
]
},
{
sentenceFirstPart: "It was Thomas Edison who ",
sentenceSecondPart: "electricity",
answerOptions: [
{ answerText: "", isCorrect: false },
{ answerText: "detected", isCorrect: false },
{ answerText: "invented", isCorrect: true },
{ answerText: "found", isCorrect: false },
{ answerText: "discovered", isCorrect: false }
]
}
];

It seems that isCorrect would need to record result of each questions and handleValueChange should probably be called on change of select to update the values in isCorrect.
Forked example with modification: codesandbox
Here isCorrect is updated as an object to save result of each question:
const [isCorrect, setIsCorrect] = useState({});
const [isChecked, setIsChecked] = useState(false);
const handleValueChange = (value, index) => {
setIsCorrect((prev) => ({
...prev,
[index]: value === "true" ? true : false,
}));
};
handleValueChange modified to pass value of option and index of the question, so isCorrect can be updated accordingly:
<Wrapper>
{DATA.map((sentence, index) => (
<Sentence isChecked={isChecked} isCorrect={isCorrect[index]} key={index}>
<span>
{index + 1}. {sentence.sentenceFirstPart}
</span>
<select onChange={(e) => handleValueChange(e.target.value, index)}>
{sentence.answerOptions.map((option, index) => (
<option value={option.isCorrect} key={index}>
{option.answerText}
</option>
))}
</select>
<span>{sentence.sentenceSecondPart}</span>
</Sentence>
))}
<button onClick={() => setIsChecked(true)}>Check</button>
</Wrapper>
In styled Sentence the select could take both isChecked and isCorrect (for this question) as conditions to set the border-color.
export const Sentence = styled.div`
display: flex;
align-items: center;
span {
font-size: 1.2rem;
}
select {
margin: 0 0.5rem;
border: 2px solid;
padding: 0.2rem;
border-radius: 4px;
font-weight: 500;
border-color: ${({ isChecked, isCorrect }) =>
!isChecked ? "currentColor" : isCorrect ? "green" : "red"};
}
`

Related

Api is getting called on every click

I have created one quiz application.The questions and answers are coming from backend API.On the browser window whenever i am clicking any answer ,API is getting called again.On every click api is getting called.How to resolve this.Can anyone help me with this?
I have tried useeffect,use state .But no success
Here is the code
import React from "react";
import "./Quiz.css";
import { useState, useEffect } from "react";
function Quiz() {
const [cname, scname] = useState([]);
const [results, finalres] = useState(false);
const [score, setScore] = useState(0);
const [currentQues, setCurrentQues] = useState(0);
//Get Method
useEffect(() => {
fetch("https://countriesnow.space/api/v0.1/countries/capital")
.then((response) => {
return response.json();
})
.then((data) => {
scname(data.data);
});
}, []);
const restartGame = () => {
setScore(0);
setCurrentQues(0);
finalres(false);
shuffledAnswers(currentQues);
};
let namearray = [5];
var capitalArray = [5];
let fx = (i) => {
let countryName = "";
let capitalName = "";
let countryNum = Math.floor(Math.random() * cname.length);
if (countryNum) {
countryName = cname[countryNum].name;
capitalName = cname[countryNum].capital;
}
namearray[i] = countryName;
capitalArray[i] = capitalName;
};
for (let i = 0; i < 5; i++) {
fx(i);
}
const shuffledAnswers = (currentQues) => {
let shuffled = questions[currentQues].answerOptions
.map((value) => ({ value, sort: Math.random() }))
.sort((a, b) => a.sort - b.sort)
.map(({ value }) => value);
// console.log(shuffled)
return shuffled;
};
const questions = [
{
questionText: "What is the capital of " + namearray[0] + "?",
answerOptions: [
{ answerText: capitalArray[0], isCorrect: true },
{ answerText: capitalArray[1], isCorrect: false },
{ answerText: capitalArray[2], isCorrect: false },
{ answerText: capitalArray[3], isCorrect: false },
],
},
{
questionText: "What is the capital of " + namearray[1] + "?",
answerOptions: [
{ answerText: capitalArray[4], isCorrect: false },
{ answerText: capitalArray[1], isCorrect: true },
{ answerText: capitalArray[0], isCorrect: false },
{ answerText: capitalArray[3], isCorrect: false },
],
},
{
questionText: "What is the capital of " + namearray[2] + "?",
answerOptions: [
{ answerText: capitalArray[1], isCorrect: false },
{ answerText: capitalArray[0], isCorrect: false },
{ answerText: capitalArray[2], isCorrect: true },
{ answerText: capitalArray[3], isCorrect: false },
],
},
{
questionText: "What is the capital of " + namearray[3] + "?",
answerOptions: [
{ answerText: capitalArray[0], isCorrect: false },
{ answerText: capitalArray[2], isCorrect: false },
{ answerText: capitalArray[1], isCorrect: false },
{ answerText: capitalArray[3], isCorrect: true },
],
},
{
questionText: "What is the capital of " + namearray[4] + "?",
answerOptions: [
{ answerText: capitalArray[4], isCorrect: true },
{ answerText: capitalArray[1], isCorrect: false },
{ answerText: capitalArray[2], isCorrect: false },
{ answerText: capitalArray[3], isCorrect: false },
],
},
];
const hoc = (isCorrect) => {
if (isCorrect === true) {
setScore(score + 1);
}
const nextq = currentQues + 1;
if (nextq < questions.length) {
setCurrentQues(nextq);
} else {
finalres(true);
}
};
console.log('data')
return (
<>
<h4>Quiz</h4>
<div id="head">Welcome User</div>
<hr />
{results ? (
<div className="final-res">
Final Results
<h4>you scored {score} out of 5</h4>
<button onClick={() => restartGame()}>Restart</button>
</div>
) : (
<div>
<div id="quescard">
<h3>
{currentQues + 1}. {questions[currentQues].questionText}
</h3>
{questions[currentQues].answerOptions.map((ansopt) => (
<button onClick={() => hoc(ansopt.isCorrect)}>
{ansopt.answerText}
</button>
))}
</div>
</div>
)}
</>
);
}
export default Quiz
The issue here is you are updating the state of the component whenever any answer option is being clicked by making them buttons.
Instead make them checkboxes and add a additional button below which would allow the user to proceed with his final selection whereby which only allowing to update the state once

Change user selected Answer buttons class depending on if isCorrect is true or false

I'm pretty new to React so aware my code is probably a bit of a mess and more complicated than it needs to be.
Currently when a user clicks an answer button "setDisabled" will disable that row of 4 buttons so the user can only select one answer button per question. The state "setButton" changes the button class to "buttonClicked" which changes the background colour to light grey (so the user can see which button they have clicked.
The score increments by 1 for each correct answer and the button "Check Answers" reveals the score.
What I am trying to do is: When the "Check Answers" button is clicked I want the buttons which the user has selected and are correct (they have isCorrect: true) to have their background colour turn green and the buttons which have been clicked by the user but are incorrect (isCorrect: false) to have their background colour turn red.
I have tried to experiment with template literals in the button className and trying some if else logic in the resultsClick function but i feel like I am tangling myself up a little in my head and potentially overcomplicating things.
Any pointers would be much appreciated.
function Quiz(props) {
const questions = [
{
questionText: 'What is the Capital of France?',
answerOptions: [
{ id: 0, answerText: 'London', isCorrect: false, answer: 0 },
{ id: 0, answerText: 'Paris', isCorrect: true, answer: 1 },
{ id: 0, answerText: 'Nice', isCorrect: false, answer: 2 },
{ id: 0, answerText: 'Lyon', isCorrect: false, answer: 3 },
],
},
{
questionText: 'What is the Capital of the UK?',
answerOptions: [
{ id: 1, answerText: 'London', isCorrect: true, answer: 4 },
{ id: 1, answerText: 'New York', isCorrect: false, answer: 5 },
{ id: 1, answerText: 'Sydney', isCorrect: false, answer: 6 },
{ id: 1, answerText: 'Bath', isCorrect: false, answer: 7 },
],
},
{
questionText: 'Who turns out to be the true victor in the Battle of Armageddon in Mortal Kombat?',
answerOptions: [
{ id: 2, answerText: 'Liu Kang', isCorrect: false, answer: 8 },
{ id: 2, answerText: 'Shang Tsung', isCorrect: false, answer: 9 },
{ id: 2, answerText: 'Raiden', isCorrect: false, answer: 10 },
{ id: 2, answerText: 'Shao Kahn', isCorrect: true, answer: 11 },
],
},
{
questionText: 'Under what pseudonym did Stephen King publish five novels between 1977 and 1984?',
answerOptions: [
{ id: 3, answerText: 'Richard Bachman', isCorrect: true, answer: 12 },
{ id: 3, answerText: 'J. D. Robb', isCorrect: false, answer: 13 },
{ id: 3, answerText: 'Mark Twain', isCorrect: false, answer: 14 },
{ id: 3, answerText: 'Lewis Carroll', isCorrect: false, answer: 15 },
],
},
];
const [startQuiz, setStartQuiz] = useState(true);
function startClick() {
setStartQuiz(current => !current);
}
const [score, setScore] = useState(0);
const optionClicked = (optionId, isCorrect, answer) => {
const newDisabledArray = [...disabled, optionId];
setDisabled(newDisabledArray)
const newClickedArray = [...button, answer];
setButton(newClickedArray);
if (isCorrect) {
setScore(score + 1);
}
}
const [button, setButton] = useState([]);
const [disabled, setDisabled] = useState([]);
const [showResults, setShowResults] = useState(true);
function resultsClick() {
setShowResults(current => !current);
}
function restartQuiz() {
setStartQuiz(current => !current);
setShowResults(current => true);
setScore(0);
setDisabled(current => []);
setButton(current => []);
}
return(
<div>
{startQuiz ?
<div className="start-screen">
<div className="start-text">
<h1>Quizzical</h1>
<p>Test your knowledge!</p>
<button onClick={startClick}>Start Quiz</button>
</div>
</div>
:
<div className="quiz">
<div className="firstQuestion">
<h2>{questions[0].questionText}</h2>
</div>
<div className="firstAnswers">
{questions[0].answerOptions.map((answerOption) => {
const {id, isCorrect, answer, answerOptions} = answerOption
return (
<button
className={button.includes(answer) ? "buttonClicked" : "button"}
key={id}
disabled={disabled.includes(id)}
onClick={() => {
optionClicked(id, isCorrect, answer);
}}
>
{answerOption.answerText}
</button>
);
}
)}
</div>
<div className="secondQuestion">
<h2>{questions[1].questionText}</h2>
</div>
<div className="secondAnswers">
{questions[1].answerOptions.map((answerOption) => {
const {id, isCorrect, answer, answerOptions} = answerOption
return (
<button
className={button.includes(answer) ? "buttonClicked" : "button"}
key={id}
disabled={disabled.includes(id)}
onClick={() => {
optionClicked(id, isCorrect, answer);
}}>
{answerOption.answerText}
</button>
);
}
)}
</div>
<div className="thirdQuestion">
<h2>{questions[2].questionText}</h2>
</div>
<div className="thirdAnswers">
{questions[2].answerOptions.map((answerOption) => {
const {id, isCorrect, answer, answerOptions} = answerOption
return (
<button
className={button.includes(answer) ? "buttonClicked" : "button"}
key={id}
disabled={disabled.includes(id)}
onClick={() => {
optionClicked(id, isCorrect, answer);
}}>
{answerOption.answerText}
</button>
);
}
)}
</div>
<div className="fourthQuestion">
<h2>{questions[3].questionText}</h2>
</div>
<div className="fourthAnswers">
{questions[3].answerOptions.map((answerOption) => {
const {id, isCorrect, answer, answerOptions} = answerOption
return (
<button
className={button.includes(answer) ? "buttonClicked" : "button"}
key={id}
disabled={disabled.includes(id)}
onClick={() => {
optionClicked(id, isCorrect, answer);
}}>
{answerOption.answerText}
</button>
);
}
)}
</div>
<br></br>
<div className="resultsSection">
<button
className="button"
onClick={()=> resultsClick()}>
Check Answers!
</button>
<h3 className="resultsText">{showResults ? <p>Score:</p> : <p>Score: {score}/4</p>}</h3>
<button className="button" onClick={restartQuiz}>Restart Quiz</button>
</div>
</div>
}
</div>
)
}```
You can set a style by checking isCorrect property withing map (at least I consider your're using). Consider this:
answerOptions?.map((answer) => (
<div style={{backgroundColor: answer.isCorrect ? 'Green' : 'Red'}}>{answer.answerText}</div>
))

Disable individual buttons in React based on Id?

I am trying to build a multiple choice quiz app using React. I am using state to increment the user's score when the correct answer button is clicked however I want the user to be able to 'click' the correct button once as a selection. I have found if the user clicks the correct answer button multiple times each click increases their score.
I have tried to apply a disable key to each of the buttons and use state to change the state to true once the button is clicked however unfortunately this affects every button.
Is there a way I can incorporate the ID in the question Array?
I want each individual answer button to be disabled once clicked.
My code so far:
const questions = [
{
questionText: 'What is the Capital of France?',
answerOptions: [
{ id: 0, answerText: 'London', isCorrect: false },
{ id: 1, answerText: 'Paris', isCorrect: true },
{ id: 2, answerText: 'Nice', isCorrect: false },
{ id: 3, answerText: 'Lyon', isCorrect: false },
],
},
{
questionText: 'What is the Capital of the UK?',
answerOptions: [
{ id: 0, answerText: 'London', isCorrect: true },
{ id: 1, answerText: 'New York', isCorrect: false },
{ id: 2, answerText: 'Sydney', isCorrect: false },
{ id: 3, answerText: 'Bath', isCorrect: false },
],
},
{
questionText: 'Who turns out to be the true victor in the Battle of Armageddon in Mortal Kombat?',
answerOptions: [
{ id: 0, answerText: 'Liu Kang', isCorrect: false },
{ id: 1, answerText: 'Shang Tsung', isCorrect: false },
{ id: 2, answerText: 'Raiden', isCorrect: false },
{ id: 3, answerText: 'Shao Kahn', isCorrect: true },
],
},
{
questionText: 'Under what pseudonym did Stephen King publish five novels between 1977 and 1984?',
answerOptions: [
{ id: 0, answerText: 'Richard Bachman', isCorrect: true },
{ id: 1, answerText: 'J. D. Robb', isCorrect: false },
{ id: 2, answerText: 'Mark Twain', isCorrect: false },
{ id: 3, answerText: 'Lewis Carroll', isCorrect: false },
],
},
];
const [startQuiz, setStartQuiz] = useState(true);
function startClick() {
setStartQuiz(current => !current);
}
const [score, setScore] = useState(0);
const optionClicked = (isCorrect) => {
if (isCorrect) {
setScore(score + 1);
}
}
const [disabled, setDisabled] = useState(false);
const [showResults, setShowResults] = useState(true);
function resultsClick() {
setShowResults(current => !current);
}
function restartQuiz() {
setStartQuiz(current => !current);
setShowResults(current => true);
setScore(0);
setDisabled(false)
}
return(
<div>
{startQuiz ?
<div className="start-screen">
<div className="start-text">
<h1>Quizzical</h1>
<p>Test your knowledge!</p>
<button onClick={startClick}>Start Quiz</button>
</div>
</div>
:
<div className="quiz">
<div className="firstQuestion">
<h2>{questions[0].questionText}</h2>
</div>
<div className="firstAnswers">
{questions[0].answerOptions.map((answerOption) => {
return (
<button key={answerOption.id}
disabled={disabled}
onClick={() => {
optionClicked(answerOption.isCorrect);
setDisabled(true);
}}>
{answerOption.answerText}
</button>
);
}
)}
</div>
<div className="secondQuestion">
<h2>{questions[1].questionText}</h2>
</div>
<div className="secondAnswers">
{questions[1].answerOptions.map((answerOption) => {
return (
<button key={answerOption.id}
disabled={disabled}
onClick={() => {
optionClicked(answerOption.isCorrect)
setDisabled(true);
}}>
{answerOption.answerText}
</button>
);
}
)}
</div>
<div className="thirdQuestion">
<h2>{questions[2].questionText}</h2>
</div>
<div className="thirdAnswers">
{questions[2].answerOptions.map((answerOption) => {
return (
<button key={answerOption.id}
disabled={disabled}
onClick={() => {
optionClicked(answerOption.isCorrect)
setDisabled(true)
}}>
{answerOption.answerText}
</button>
);
}
)}
</div>
<div className="fourthQuestion">
<h2>{questions[3].questionText}</h2>
</div>
<div className="fourthAnswers">
{questions[3].answerOptions.map((answerOption) => {
return (
<button key={answerOption.id}
disabled={disabled}
onClick={() => {
optionClicked(answerOption.isCorrect)
setDisabled(true)
}}>
{answerOption.answerText}
</button>
);
}
)}
</div>
<br></br>
<div className="resultsSection">
<button onClick={()=> resultsClick()}>
Check Answers!
</button>
<h3 className="resultsText">{showResults ? <p>Score:</p> : <p>Score: {score}/4</p>}</h3>
<button onClick={restartQuiz}>Restart Quiz</button>
</div>
</div>
}
</div>
)
}```
First and foremost, it would be great if you could create a reusable component for each set of question+answers to avoid writing too much repeated code e.g.
function Question({questionText, answerOptions}) {
return <>
<div className="question">
<h2>{questionText}</h2>
</div>
<div className="answers">
{answerOptions.map((answerOption) => {
return (
<button key={answerOption.id}
disabled={disabled}
onClick={() => {
optionClicked(answerOption.isCorrect)
setDisabled(true)
}}>
{answerOption.answerText}
</button>
)
}
)}
</div>
</>
}
Next, you could use the useState hook to store an array of numbers indicating which answer option has been clicked:
const [disabledOptions, setDisabledOptions] = useState([])
Edit the optionClicked function such that it receives both the option id and the isCorrect boolean, and add the option id to the disabledOptions array
const optionClicked = (optionId, isCorrect) => {
const newDisabledArray = [...disabledOptions, optionId];
setDisabledOptions(newDisabledArray);
if (isCorrect){
setScore(score + 1);
}
}
Final code will look something like this:
function Question({questionText, answerOptions}) {
const [disabledOptions, setDisabledOptions] = useState([])
const optionClicked = (optionId, isCorrect) => {
const newDisabledArray = [...disabledOptions, optionId];
setDisabledOptions(newDisabledArray);
if (isCorrect){
setScore(score + 1);
}
}
return <>
<div className="question">
<h2>{questionText}</h2>
</div>
<div className="answers">
{answerOptions.map((answerOption) => {
const {id, isCorrect, answerText} = answerOption;
return (
<button key={id}
disabled={disabledOptions.includes(id)}
onClick={() => {
optionClicked(id, isCorrect)
}}>
{answerText}
</button>
)
}
)}
</div>
</>
}

create card using array of data react

hi everyone I have data given below by using this data I just want to create a cart click on this link to check what kind of cart I want to design from this data
const result = [
{
name: 'shanu',
label: ['ak', 'pk', 'plk', 'k'],
value: [1, 2, 3, 5],
},
];
// what i did
{result.map((el) => {
return (
<div>
<h1>{el.name}</h1>
<div className="vart">
<div>
{el.label.map((e) => {
return <p>{e}</p>;
})}
</div>
<div>
{el.value.map((e) => {
return <p>{e}</p>;
})}
</div>
</div>
</div>
);
})}
.vart {
display: flex;
flex-direction: row;
}
You can access the value according to the index of the label as below. You can use a CSS grid system to show a two-column view.
export default function App() {
const result = [
{
name: "shanu",
label: ["ak", "pk", "plk", "k"],
value: [1, 2, 3, 5]
}
];
return result.map((el) => {
return (
<div>
<div className="header">{el.name}</div>
<div className="grid-container">
{el.label.map((e, index) => {
return (
<div
className="grid-item"
style={{ textAlign: index % 2 === 0 ? "left" : "right" }}
>
{e} : {el.value[index]}
</div>
);
})}
</div>
</div>
);
});
}
Following styles will organise the grid with right aligning the second column.
.header {
color: #ffffff;
background-color: #4473c4;
padding: 10px 20px;
}
.grid-container {
display: grid;
grid-template-columns: auto auto;
}
.grid-item {
padding: 10px 20px;
color: #ffffff;
background-color: #91cf50;
}
HTML Output
Code Sandbox
If you want to link value and label this way:
ak => 1
pk => 2
plk => 3
k => 5
It would be better practice to change your data structure and move them aside. It avoids running in cases where label[x] is defined, but value[x] is not:
export default function App() {
const result = [
{
name: "shanu",
items: [
{ label: "ak", value: 1 },
{ label: "pk", value: 2 },
{ label: "plk", value: 3 },
{ label: "k", value: 5 },
],
}
];
return result.map((el) => {
return (
<div>
<h1>{el.name}</h1>
<div className="vart">
<div>
{el.items.map((e, index) => {
return (
<p>
{e.label} : {e.value}
</p>
);
})}
</div>
</div>
</div>
);
});
}

Filtering by multiple items in React

I am trying to filter the list of items in state.items by adding items from state.filterItems to my state.filter array
if I use this.state.items.filter(items => items.cat === 'veg' ) of course this works but I need to be able to filter dynamically using the list of items added to my state.filter array and I'm not sure how to do this,
I would also like to be able select multiple options and then hit a button to apply the filters rather than selecting them one by one
https://www.webpackbin.com/bins/-KoCT_DiT2CNLz8ddr4O
Hello.js
import React, { Component } from 'react';
import logo from './logo.svg'
import './App.css'
import update from 'immutability-helper'
import TodoList from './TodoList'
import styled from 'styled-components'
import FilterList from './FilterList'
const Wrapper = styled.div`
max-width:1280px;
background: papayawhip;
margin: 0 auto;
padding:20px;
`
const Grid = styled.div`
display:flex;
flex-wrap:wrap;
`
const Cell = styled.div`
flex: 0 0 25%;
padding: 20px;
`
export default class hello extends Component {
constructor(props) {
super(props)
this.state = {
items: [
{id: 1, cat: 'fruit', text: 'apples'},
{id: 2, cat: 'fruit', text: 'oranges'},
{id: 3, cat: 'fruit', text: 'peaches'},
{id: 4, cat: 'veg', text: 'carrots'},
{id: 5, cat: 'veg', text: 'aubergine'},
{id: 6, cat: 'veg', text: 'peaches'},
{id: 7, cat: 'bread', text: 'olive bread'},
{id: 8, cat: 'bread', text: 'bread roll'},
{id: 9, cat: 'bread', text: 'bagel'},
],
filterItems: [
{id: 1, text: 'bread'},
{id: 2, text: 'fruit'},
{id: 3, text: 'vegetables'},
],
filter: [
{text: 'bread'}
],
}
}
handleFilterChange = (filter) => {
this.setState({filter: filter})
}
render() {
return (
<Wrapper>
<div>
<FilterList
value={this.state.filter}
onChange={this.handleFilterChange}
filterItems={this.state.filterItems}
/>
</div>
<Grid>
{
this.state.items.filter(items => items.cat === 'veg', 'fruit' )
.map(item =>
<Cell>
{console.log(this.state.filter.text)}
<div>{item.cat}</div>
<div>{item.text}</div>
</Cell>
)
}
</Grid>
</Wrapper>
)
}
}
// <pre>{JSON.stringify(this.state, null, 4)} </pre>
FilterList.js
import React, { Component } from 'react';
import TodoItem from './TodoItem'
import update from 'immutability-helper'
import styled from 'styled-components'
const FilterListBg = styled.div`
background: lightblue;
width: 100%;
height: 60px;
`
const FilterListItem = styled.div`
float: left;
height: 40px;
width: 100px;
padding:10px;
border-right: 1px solid #ff00ff;
`
const FilterBg = styled.div`
width: 100%;
height:40px;
background: #fff;
margin-top:20px;
`
const FilterItem = styled.div`
float: left;
height: 40px;
width: 100px;
padding:10px;
border-right: 1px solid #ff00ff;
`
export default class FilterList extends Component {
constructor() {
super()
this.state = {
search: ''
}
}
handleAdd = (item) => {
const value = update(this.props.value, {
$push: [
{
text: item,
id: Math.random(),
}
]
})
this.props.onChange(value)
}
handleRemove = (index) => {
const value = update(this.props.value, {
$splice: [
[index, 1]
]
})
this.props.onChange(value)
}
handleFilterUpdate = event => {
this.setState({ search: event.target.value })
}
render() {
return (
<div>
<input
type="text"
value={this.state.search}
onChange={this.handleFilterUpdate}
placeholder="Hledat podle nazvu"
/>
{this.state.search}
<FilterListBg>
{
this.props.filterItems.filter(items => items.text.toLowerCase().indexOf(this.state.search.toLowerCase()) >= 0)
.map((item,cat,index) =>
<FilterListItem key={item.id} onClick={()=>this.handleAdd(item.text)}>
{item.text}
</FilterListItem>
)
}
</FilterListBg>
AktivnĂ­ filtry
<FilterBg>
{
this.props.value.map((item, index) =>
<FilterItem key={item.id} onClick={this.handleRemove}>
{item.text}
</FilterItem>
)
}
</FilterBg>
</div>
)
}
}
Assuming you want to show the items matching your filterList, shouldn't something simple like this work?
const filterTexts = this.state.filter.map(item => item.text);
const itemsToShow = this.state.items.filter(
item => filterTexts.indexOf(item.cat) !== -1);
And then you can map over itemsToShow to create your Cells.
If you want a one-liner to simply copy-paste:
this.state.items.filter(items => this.state.filterItems.map(item => item.text)
.indexOf(items.cat) !== -1 )
.map(item =>
<Cell>
{console.log(this.state.filter.text)}
<div>{item.cat}</div>
<div>{item.text}</div>
</Cell>
)

Categories

Resources