gpt4 book ai didi

javascript - 使用 react 备忘录动态更改样式

转载 作者:行者123 更新时间:2023-12-04 08:09:49 24 4
gpt4 key购买 nike

我正在学习使用react memo,我将它应用到一个简单的任务应用程序中,我的问题是我不知道如何使列表中项目的样式很好地工作。
Image from Gyazo
正如你在完成一项任务时所看到的,我不知道如何更新列表中其他项目的样式,使其一白一黑。
我尝试了很多东西,但没有任何效果:(
任务项.jsx

import React, { memo } from 'react'
import styled from "styled-components"
import { useSelector } from "react-redux";
import store from "../../redux/store";

//STYLES

const DIV = styled.div`

max-height: ${
props => !useSelector((state)=> state.toggleDoneTasks.show) && props.done ? "0px" : "50px"
};

opacity: ${
props => !useSelector((state)=> state.toggleDoneTasks.show) && props.done ? "0": "1"
};

padding: ${
props => !useSelector((state)=> state.toggleDoneTasks.show) && props.done ? "0px":"12px 15px"
};

overflow: hidden;
transition: opacity 0.5s, max-height 0.5s, padding 0.5s;
`;

const TR = styled.tr`
background-color: ${
(props) => {

//show completed and not completed tasks
if(useSelector((state)=> state.toggleDoneTasks.show)){
return props.index % 2 === 0 ? '#f3f3f3': 'none'
}

const tasksNotDone = props.tasks.filter((task) => !task.done)
const index = tasksNotDone.findIndex(t => t.id === props.task.id)
return index % 2 === 0 ? '#f3f3f3': 'none'

}
};

/*
&:nth-child(even) {background: #CCC};
&:nth-child(odd) {background: #FFF};
*/

border-bottom: ${
props => !useSelector((state)=> state.toggleDoneTasks.show) && props.task.done ? "none": "1px solid #dddddd"
};;

transition: visibility 0.5s;

cursor: pointer;
&:hover{
font-weight: bold;
color: #009879;
}
`;


function TaskRow({ task, toggleDoneTask, index, tasks }) {

return (

<TR task={task} tasks={tasks} index={index}>
<td>
<DIV done={task.done}>
{console.log('render', task)}
{task.title}
</DIV>
</td>
<td>
<DIV done={task.done}>
{task.description}
</DIV>
</td>
<td>
<DIV done={task.done}>
<input type="checkbox"
checked={task.done}
onChange={toggleDoneTask}
style={{cursor: 'pointer'}}
/>
</DIV>
</td>
</TR>
)
}


export default memo(TaskRow, (prev, next) => {
// store.getState().toggleDoneTasks.show

//COMPARE TASK OBJECT
const prevTaskKeys = Object.keys(prev.task);
const nextTaskKeys = Object.keys(next.task);

const sameLength = prevTaskKeys.length === nextTaskKeys.length;
const sameEntries = prevTaskKeys.every(key => {
return nextTaskKeys.includes(key) && prev.task[key] === next.task[key];
});

return sameLength && sameEntries;
})
任务.jsx
import React, { useEffect, useReducer } from "react";
import TaskItem from "./TaskItem";

function saveLocalStorage(tasks) {
localStorage.setItem("tasks", JSON.stringify(tasks));
}

function TasksReducer(taskItems, { type, task }) {
switch (type) {
case "UPDATE_TAKS": {
let taskItemsCopy = [...taskItems].map((task) => ({ ...task }));
let newItems = taskItemsCopy.map((t) => {
if (t.id === task.id) {
t.done = !t.done;
}
return t;
});
saveLocalStorage(newItems);
return newItems;
}

case "ADD_TASK": {
const newItems = [...taskItems, task];
saveLocalStorage(newItems);
return newItems;
}

default:
window.alert("INVALID ACTION");
break;
}
}

const initialState = JSON.parse(localStorage.getItem("tasks")) || [];

//STYLES

const styleTable = {
borderCollapse: "collapse",
margin: "25px 0",
fontSize: "0.9em",
fontFamily: "sans-serif",
minWidth: "400px",
boxShadow: "0 0 20px rgba(0, 0, 0, 0.15)"
};

const styleTr = {
backgroundColor: "#009879",
color: "#ffffff",
textAlign: "left"
};

const styleTh = {
padding: "12px 15px"
};

function Tasks({ newTask, show }) {
const [taskItems, dispatch] = useReducer(TasksReducer, initialState);

useEffect(() => {
if (!newTask) return;
newTaskHandler({ id: taskItems.length + 1, ...newTask });
}, [newTask]);

const newTaskHandler = (task) => {
dispatch({ type: "ADD_TASK", task });
};

const toggleDoneTask = (task) => {
dispatch({ type: "UPDATE_TAKS", task });
};

return (
<React.Fragment>
<h1>learning react </h1>
<table style={styleTable}>
<thead>
<tr style={styleTr}>
<th style={styleTh}>Title</th>
<th style={styleTh}>Description</th>
<th style={styleTh}>Done</th>
</tr>
</thead>
<tbody>
{taskItems.map(
(task, i) =>
(show || !task.done) && (
<TaskItem
tasks={taskItems}
index={i}
task={task}
key={task.id}
show={show}
toggleDoneTask={() => toggleDoneTask(task)}
/>
)
)}
</tbody>
</table>
</React.Fragment>
);
}

export default Tasks;
如果您需要完整的代码:
Edit inspiring-sea-hp9kt

最佳答案

关于备忘录和您的应用Memo当您不希望您的组件经常更改时,它可能很有用。它伴随着进行这些评估以验证是否应该重新渲染的成本。
在您的情况下,您将有很多重新渲染,因为需要重新渲染多个组件以适应正确的背景,这是使用 Memo 的缺点。 .
此外,您会看到这些错误,因为其他组件不会重新渲染,因为它们的 Prop 不会改变。
我建议删除这种情况下的备忘录。
关于你的节目状态
你看到你的 Accordion 效果了吗?如果组件确实卸载了,您将不会看到这种效果。这意味着组件永远不会卸载。您正在使用 2 show状态,一个状态在您的应用程序的根创建,另一个状态来自您的 reducer 。
您的按钮只会翻转 reducer show状态。但要渲染 TaskItem您使用创建的陈旧显示状态,这始终是正确的。如果您使用的是 redux 状态,则根本不会有任何影响:

// show is always true unless you pass state from your reducer like:
// const show = useSelector((state) => state.toggleDoneTasks.show);
(show || !task.done) && (
<TaskItem
tasks={taskItems}
index={i}
task={task}
key={task.id}
show={show}
toggleDoneTask={() => toggleDoneTask(task)}
/>
)
所以你应该删除你的 React 显示状态:
const [show, setShow] = useState(JSON.parse(localStorage.getItem('show')) || true)
或者删除您的 reducer ,但出于学习目的,您可以保留 reducer 。
沙盒没有额外的状态,也没有效果:
sandbox
关于 Accordion 效果
鉴于您将不再有 Accordion 效果。为了解决这个问题,您可以:
  • 选择一个 react 动画库,它可以处理您偏好的组件安装和卸载的过渡效果;
  • 渲染所有任务(没有 (show || !task.done) 条件)。并跟踪每个 Task 有多少个任务 done直到那个给定的任务。有了它,您可以执行一些逻辑,例如:
  •     const indexToPass = show ? index : index - doneTasksBefore 

    ...

    <TR task={task} tasks={tasks} index={indexToPass}>

    关于javascript - 使用 react 备忘录动态更改样式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66039067/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com