React:我可以在不引起重绘的情况下更改状态 (useState),以便我可以看到 css 转换吗?
React: can I change a state (useState) without causing a repaint, so that I can see a css transition?
我有不同的"cards"点击onClick
我希望他们的margin-left
属性被修改
为此我使用 useState
,为此我只有一个状态,它是一个存储所有卡片状态的对象
下面的示例代码显示了问题,但没有组件 <Type>
并使用简单 elements
数组的简化版本按预期工作
所以,如果我需要使用像下面这样的结构,我该如何保持过渡效果?
示例代码
https://codesandbox.io/s/keen-shadow-2v16s?fontsize=14&hidenavigation=1&theme=dark
import React, { useState } from "react";
import styled from "@emotion/styled";
export default function App() {
const [userTap, setUserTap] = useState({});
const elements1 = [...Array(5)];
const elements2 = [...Array(3)];
const Type = ({ list }) =>
list.map((el, i) => (
<Ingredient
key={"draggable" + i}
onClick={e => {
e.stopPropagation();
e.preventDefault();
userTap[i] = userTap[i] ? 0 : 1;
setUserTap({ ...userTap }); // create a new ref to provoke the rerender
return;
}}
userTap={userTap[i]}
>
<div>item</div>
</Ingredient>
));
return (
<>
<Type list={elements1} />
<Type list={elements2} />
</>
);
}
const Ingredient = styled.li`
list-style: none;
cursor: pointer;
margin: 5px;
padding: 5px;
background: #ccc;
border-radius: 3px;
width: 50px;
margin-left: ${props => (props.userTap ? "100px" : "15px")};
transition: all 0.2s ease-in;
`;
正如@larz 在评论中建议的那样,唯一需要做的就是将 useState
移动到最后一个组件,如下所示
https://codesandbox.io/s/affectionate-hawking-5p81d?fontsize=14&hidenavigation=1&theme=dark
import React, { useState } from "react";
import styled from "@emotion/styled";
export default function App() {
const elements1 = [...Array(5)];
const elements2 = [...Array(3)];
const Type = ({ list, type }) => {
const [userTap, setUserTap] = useState({});
return list.map((el, i) => (
<Ingredient
key={"draggable" + i}
onClick={e => {
e.stopPropagation();
e.preventDefault();
userTap[type + i] = userTap[type + i] ? 0 : 1;
setUserTap({ ...userTap }); // create a new ref to provoke the rerender
return;
}}
userTap={userTap[type + i]}
>
<div>item</div>
</Ingredient>
));
};
return (
<>
<Type list={elements1} type="one" />
<Type list={elements2} type="two" />
</>
);
}
const Ingredient = styled.li`
list-style: none;
cursor: pointer;
margin: 5px;
padding: 5px;
background: #ccc;
border-radius: 3px;
width: 50px;
margin-left: ${props => (props.userTap ? "100px" : "15px")};
transition: all 0.2s ease-in;
`;
我有不同的"cards"点击onClick
我希望他们的margin-left
属性被修改
为此我使用 useState
,为此我只有一个状态,它是一个存储所有卡片状态的对象
下面的示例代码显示了问题,但没有组件 <Type>
并使用简单 elements
数组的简化版本按预期工作
所以,如果我需要使用像下面这样的结构,我该如何保持过渡效果?
示例代码
https://codesandbox.io/s/keen-shadow-2v16s?fontsize=14&hidenavigation=1&theme=dark
import React, { useState } from "react";
import styled from "@emotion/styled";
export default function App() {
const [userTap, setUserTap] = useState({});
const elements1 = [...Array(5)];
const elements2 = [...Array(3)];
const Type = ({ list }) =>
list.map((el, i) => (
<Ingredient
key={"draggable" + i}
onClick={e => {
e.stopPropagation();
e.preventDefault();
userTap[i] = userTap[i] ? 0 : 1;
setUserTap({ ...userTap }); // create a new ref to provoke the rerender
return;
}}
userTap={userTap[i]}
>
<div>item</div>
</Ingredient>
));
return (
<>
<Type list={elements1} />
<Type list={elements2} />
</>
);
}
const Ingredient = styled.li`
list-style: none;
cursor: pointer;
margin: 5px;
padding: 5px;
background: #ccc;
border-radius: 3px;
width: 50px;
margin-left: ${props => (props.userTap ? "100px" : "15px")};
transition: all 0.2s ease-in;
`;
正如@larz 在评论中建议的那样,唯一需要做的就是将 useState
移动到最后一个组件,如下所示
https://codesandbox.io/s/affectionate-hawking-5p81d?fontsize=14&hidenavigation=1&theme=dark
import React, { useState } from "react";
import styled from "@emotion/styled";
export default function App() {
const elements1 = [...Array(5)];
const elements2 = [...Array(3)];
const Type = ({ list, type }) => {
const [userTap, setUserTap] = useState({});
return list.map((el, i) => (
<Ingredient
key={"draggable" + i}
onClick={e => {
e.stopPropagation();
e.preventDefault();
userTap[type + i] = userTap[type + i] ? 0 : 1;
setUserTap({ ...userTap }); // create a new ref to provoke the rerender
return;
}}
userTap={userTap[type + i]}
>
<div>item</div>
</Ingredient>
));
};
return (
<>
<Type list={elements1} type="one" />
<Type list={elements2} type="two" />
</>
);
}
const Ingredient = styled.li`
list-style: none;
cursor: pointer;
margin: 5px;
padding: 5px;
background: #ccc;
border-radius: 3px;
width: 50px;
margin-left: ${props => (props.userTap ? "100px" : "15px")};
transition: all 0.2s ease-in;
`;