I am creating a simple tracker which records all the activities done. It is my first project in react. I have created three state one for storing all the items(name of state is list), one for pending items(name of state is pending) , one for completed items(name of state is completed). The items have a button which when clicked marks it into done state and vice-versa. It is completely rendering items for main list. But for other two its not rendering. When I am checking with react developer tools, it is working fine, i.e. it is adding to pending list or completed list as it should. But it is not compiling them on screen. list is already filled with items. I have added all the code for just in case.
function Filters(props){
const [completed, setCompleted] = useState([]);
const [pending, setPending] = useState([]);
const [state, setState] = useState("None");
const [list,setList] = useState([]);
function viewState(){
setState("View-all");
}
//it is getting the clicked item id and marking it complete in main list
function markComplete(id){
list.map((items,index)=>{
if(index===id){
if(items.done===true)
items.done = false;
else{
items.done=true;
}
}
})
}
//i am simply scanning the main list and the items which are pending will be added to this list. //this happens whenever the person click on pending button
function pendingState(){
setState("pending-all");
setPending([]);
list.map(items=>{
if(items.done!==true){
setPending(prev=>{
return [...prev,items];
})
}
})
}
function completedState(){
setState("completed-all");
setCompleted([]);
list.map(items=>{
if(items.done===true){
setCompleted(prev=>{
return [...prev,items];
})
}
})
}
return (
<div>
<div className="input-section">
<Note setList={setList} />
</div>
<button type="button" onClick={viewState} >View All</button>
<button type="button" onClick={completedState}>Completed</button>
<button type="button" onClick={pendingState}>Pending</button>
<div>
{
(()=>{
if(state==="View-all")
{
return (
<div>
<h1>Working {completed}</h1>
{(list).map((items,index)=>
{
return (
<Excercise
key={index}
id={index}
title={items.name}
list={props.list}
setList={props.setList}
content={items.desp}
markComplete={markComplete}
/>
)
})}
</div>
)
}
else if(state==="completed-all")
{
return (
<div>
{completed.map((items,index)=>{
<Excercise
key={index}
id={index}
title={items.name}
list={props.list}
setList={props.setList}
content={items.desp}
markComplete={markComplete}
/>
})}
</div>
)
}
})()
}
</div>
</div>);
}
Kindly help. Thank you.
Hi @DREW The function code :
function markComplete(id){
setList(lists=>{
lists.map(item=>{
return item.id===id ?{...item,done: !item.done} : (item);})
}
)
}
When I am using it instead of
const markComplete = (id) => {
setList((list) =>
list.map((item) =>
item.id === id
? {
...item,
done: !item.done
}
: item
)
);
};
it is showing, "Cannot read properties of undefined (reading 'filter')" arent the both same. If not, what am I doing wrong. Sorry for bugging so many times, I have just started with react.
I think you've overcomplicated things a bit. You only need one array to store the exercises in, the "pending" and "completed" states are easily derived from the list
state and the state
filter state value.
markComplete
callback is mutating the list
state. When updating the list
state not only is a new array reference necessary, but also new element object references are necessary for the elements that are being updated.viewState
, pendingState
, and completedState
handlers to simply set the filter value, and then derive the computed state when rendering by adding an inline filter
function.id
property as a React key and as the property used for toggling the completed (done
) state.function Filters(props) {
const [state, setState] = useState("None");
const [list, setList] = useState([
...
]);
function viewState() {
setState("View-all");
}
function pendingState() {
setState("pending-all");
}
function completedState() {
setState("completed-all");
}
const markComplete = (id) => {
setList((list) =>
list.map((item) =>
item.id === id
? {
...item,
done: !item.done
}
: item
)
);
};
return (
<div>
<div className="input-section">
<Note setList={setList} />
</div>
<button type="button" onClick={viewState}>
View All
</button>
<button type="button" onClick={completedState}>
Completed
</button>
<button type="button" onClick={pendingState}>
Pending
</button>
<div>
{list
.filter((item) => {
if (state === "pending-all") {
return !item.done;
} else if (state === "completed-all") {
return item.done;
}
return true;
})
.map((item) => (
<Excercise
key={item.id}
id={item.id}
done={item.done}
title={item.name}
content={item.desp}
markComplete={markComplete}
/>
))}
</div>
</div>
);
}