改变 translateX() 转换方向的 ReactJS 问题
ReactJS problem with changing direction of translateX() transformation
给定:
function App() {
const [xPos, setXPos ] = React.useState(0);
const [style, setStyle] = React.useState({transform: `translateX(${xPos}px)`});
const onClick =(direction) => {
(direction === "left") ? setXPos(x => x-100) : setXPos(x => x +100);
setStyle({transform: `translateX(${xPos}px)`});
console.log(xPos)
}
return (
<div className="main_container">
<button className="left_button" onClick={() => onClick("left")}>slide left</button>
<div className="forecast_slider" >
<div className="forecast_container" style={style} >
{forecastBuilder()}
</div>
</div>
<button className="right_button" onClick={() => onClick("right")}>slide right</button>
</div>
)
}
const forecastBuilder = () => {
const cell = [];
for(var i = 1 ; i < 8 ; i++){
cell.push(
<div className={i}>
{i}
<img src="https://imgs.michaels.com/MAM/assets/1/5E3C12034D34434F8A9BAAFDDF0F8E1B/img/0E9397ED92304202B4A25D7387A74515/M10118706_2.jpg" width="100" height="80" border="1px solid black" />
<br></br>
<span>day {i}</span>
</div>
)
}
return cell;
}
ReactDOM.render(<App />, document.querySelector("#app"));
.main_container {
display:flex;
}
.forecast_container {
display: flex;
width: 510px;
height: 130px;
margin-left: auto;
margin-right: auto;
align-items: center;
text-align: center;
transition: transform 250ms;
}
.forecast_slider {
background-color: black;
color: white;
overflow:hidden;
float:right;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="app"></div>
我想让translateX()
动画正常递增递减。目前,我必须点击两次按钮才能改变方向。我不知道为什么会这样。我尝试将初始 style
的转换参数设置为 0px
。老实说,我还没有尝试过其他东西,我缺乏想法,这个错误超出了我对 React 的理解。
有人知道我该如何解决这个问题吗?
已找到答案。
设置状态不是同步的,没有理由将 style
存储在额外的状态挂钩中,因为它只是一个参数,可以立即传递到渲染函数中。
const [xPos, setXPos ] = React.useState(0);
const onClick =(direction) => {
(direction === "left") ? setXPos(x => x-100) : setXPos(x => x +100);
}
return (
<div className="main_container">
<button className="left_button" onClick={() => onClick("left")}>slide left</button>
<div className="forecast_slider" >
<div className="forecast_container" style={{transform : `translateX(${xPos}px)`}} >
{forecastBuilder()}
</div>
</div>
<button className="right_button" onClick={() => onClick("right")}>slide right</button>
</div>
)
解决了问题。
问题是您在“更新”后立即尝试在 onClick
处理程序中使用更新的 xPos
状态:setStyle({transform: `translateX(${xPos}px)`})
不要忘记 useState
就像 class 组件中的 setState
一样是异步的。您不能在一行上更新状态并假设它已经在下一行上更改。您可能会使用未更改的状态。
创建一个新变量并使用该变量更新两个状态:
function App() {
const [xPos, setXPos] = React.useState(0);
const [style, setStyle] = React.useState({
transform: `translateX(${xPos}px)`,
});
const onClick = (direction) => {
let x = direction === 'left' ? xPos - 100 : xPos + 100
setXPos(x)
setStyle({ transform: `translateX(${x}px)` });
console.log(xPos);
};
return (
<div className="main_container">
<button className="left_button" onClick={() => onClick('left')}>
slide left
</button>
<div className="forecast_slider">
<div className="forecast_container" style={style}>
{forecastBuilder()}
</div>
</div>
<button className="right_button" onClick={() => onClick('right')}>
slide right
</button>
</div>
);
}
const forecastBuilder = () => {
const cell = [];
for (var i = 1; i < 8; i++) {
cell.push(
<div className={i}>
{i}
<img
src="https://imgs.michaels.com/MAM/assets/1/5E3C12034D34434F8A9BAAFDDF0F8E1B/img/0E9397ED92304202B4A25D7387A74515/M10118706_2.jpg"
width="100"
height="80"
border="1px solid black"
/>
<br></br>
<span>day {i}</span>
</div>
);
}
return cell;
};
ReactDOM.render(<App />, document.querySelector('#app'));
.main_container {
display: flex;
}
.forecast_container {
display: flex;
width: 510px;
height: 130px;
margin-left: auto;
margin-right: auto;
align-items: center;
text-align: center;
transition: transform 250ms;
}
.forecast_slider {
background-color: black;
color: white;
overflow: hidden;
float: right;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="app"></div>
此外,您可以简单地摆脱 useStyles
钩子,因为它只是 xPos
:
周围的一些额外的绒毛
function App() {
const [xPos, setXPos] = React.useState(0);
return (
<div className="main_container">
<button className="left_button" onClick={() => setXPos(xPos - 100)}>
slide left
</button>
<div className="forecast_slider">
<div className="forecast_container" style={{ transform: `translateX(${xPos}px)` }}>
{forecastBuilder()}
</div>
</div>
<button className="right_button" onClick={() => setXPos(xPos + 100)}>
slide right
</button>
</div>
);
}
const forecastBuilder = () => {
const cell = [];
for (var i = 1; i < 8; i++) {
cell.push(
<div className={i}>
{i}
<img
src="https://imgs.michaels.com/MAM/assets/1/5E3C12034D34434F8A9BAAFDDF0F8E1B/img/0E9397ED92304202B4A25D7387A74515/M10118706_2.jpg"
width="100"
height="80"
border="1px solid black"
/>
<br></br>
<span>day {i}</span>
</div>
);
}
return cell;
};
ReactDOM.render(<App />, document.querySelector('#app'));
.main_container {
display: flex;
}
.forecast_container {
display: flex;
width: 510px;
height: 130px;
margin-left: auto;
margin-right: auto;
align-items: center;
text-align: center;
transition: transform 250ms;
}
.forecast_slider {
background-color: black;
color: white;
overflow: hidden;
float: right;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="app"></div>
给定:
function App() {
const [xPos, setXPos ] = React.useState(0);
const [style, setStyle] = React.useState({transform: `translateX(${xPos}px)`});
const onClick =(direction) => {
(direction === "left") ? setXPos(x => x-100) : setXPos(x => x +100);
setStyle({transform: `translateX(${xPos}px)`});
console.log(xPos)
}
return (
<div className="main_container">
<button className="left_button" onClick={() => onClick("left")}>slide left</button>
<div className="forecast_slider" >
<div className="forecast_container" style={style} >
{forecastBuilder()}
</div>
</div>
<button className="right_button" onClick={() => onClick("right")}>slide right</button>
</div>
)
}
const forecastBuilder = () => {
const cell = [];
for(var i = 1 ; i < 8 ; i++){
cell.push(
<div className={i}>
{i}
<img src="https://imgs.michaels.com/MAM/assets/1/5E3C12034D34434F8A9BAAFDDF0F8E1B/img/0E9397ED92304202B4A25D7387A74515/M10118706_2.jpg" width="100" height="80" border="1px solid black" />
<br></br>
<span>day {i}</span>
</div>
)
}
return cell;
}
ReactDOM.render(<App />, document.querySelector("#app"));
.main_container {
display:flex;
}
.forecast_container {
display: flex;
width: 510px;
height: 130px;
margin-left: auto;
margin-right: auto;
align-items: center;
text-align: center;
transition: transform 250ms;
}
.forecast_slider {
background-color: black;
color: white;
overflow:hidden;
float:right;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="app"></div>
我想让translateX()
动画正常递增递减。目前,我必须点击两次按钮才能改变方向。我不知道为什么会这样。我尝试将初始 style
的转换参数设置为 0px
。老实说,我还没有尝试过其他东西,我缺乏想法,这个错误超出了我对 React 的理解。
有人知道我该如何解决这个问题吗?
已找到答案。
设置状态不是同步的,没有理由将 style
存储在额外的状态挂钩中,因为它只是一个参数,可以立即传递到渲染函数中。
const [xPos, setXPos ] = React.useState(0);
const onClick =(direction) => {
(direction === "left") ? setXPos(x => x-100) : setXPos(x => x +100);
}
return (
<div className="main_container">
<button className="left_button" onClick={() => onClick("left")}>slide left</button>
<div className="forecast_slider" >
<div className="forecast_container" style={{transform : `translateX(${xPos}px)`}} >
{forecastBuilder()}
</div>
</div>
<button className="right_button" onClick={() => onClick("right")}>slide right</button>
</div>
)
解决了问题。
问题是您在“更新”后立即尝试在 onClick
处理程序中使用更新的 xPos
状态:setStyle({transform: `translateX(${xPos}px)`})
不要忘记 useState
就像 class 组件中的 setState
一样是异步的。您不能在一行上更新状态并假设它已经在下一行上更改。您可能会使用未更改的状态。
创建一个新变量并使用该变量更新两个状态:
function App() {
const [xPos, setXPos] = React.useState(0);
const [style, setStyle] = React.useState({
transform: `translateX(${xPos}px)`,
});
const onClick = (direction) => {
let x = direction === 'left' ? xPos - 100 : xPos + 100
setXPos(x)
setStyle({ transform: `translateX(${x}px)` });
console.log(xPos);
};
return (
<div className="main_container">
<button className="left_button" onClick={() => onClick('left')}>
slide left
</button>
<div className="forecast_slider">
<div className="forecast_container" style={style}>
{forecastBuilder()}
</div>
</div>
<button className="right_button" onClick={() => onClick('right')}>
slide right
</button>
</div>
);
}
const forecastBuilder = () => {
const cell = [];
for (var i = 1; i < 8; i++) {
cell.push(
<div className={i}>
{i}
<img
src="https://imgs.michaels.com/MAM/assets/1/5E3C12034D34434F8A9BAAFDDF0F8E1B/img/0E9397ED92304202B4A25D7387A74515/M10118706_2.jpg"
width="100"
height="80"
border="1px solid black"
/>
<br></br>
<span>day {i}</span>
</div>
);
}
return cell;
};
ReactDOM.render(<App />, document.querySelector('#app'));
.main_container {
display: flex;
}
.forecast_container {
display: flex;
width: 510px;
height: 130px;
margin-left: auto;
margin-right: auto;
align-items: center;
text-align: center;
transition: transform 250ms;
}
.forecast_slider {
background-color: black;
color: white;
overflow: hidden;
float: right;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="app"></div>
此外,您可以简单地摆脱 useStyles
钩子,因为它只是 xPos
:
function App() {
const [xPos, setXPos] = React.useState(0);
return (
<div className="main_container">
<button className="left_button" onClick={() => setXPos(xPos - 100)}>
slide left
</button>
<div className="forecast_slider">
<div className="forecast_container" style={{ transform: `translateX(${xPos}px)` }}>
{forecastBuilder()}
</div>
</div>
<button className="right_button" onClick={() => setXPos(xPos + 100)}>
slide right
</button>
</div>
);
}
const forecastBuilder = () => {
const cell = [];
for (var i = 1; i < 8; i++) {
cell.push(
<div className={i}>
{i}
<img
src="https://imgs.michaels.com/MAM/assets/1/5E3C12034D34434F8A9BAAFDDF0F8E1B/img/0E9397ED92304202B4A25D7387A74515/M10118706_2.jpg"
width="100"
height="80"
border="1px solid black"
/>
<br></br>
<span>day {i}</span>
</div>
);
}
return cell;
};
ReactDOM.render(<App />, document.querySelector('#app'));
.main_container {
display: flex;
}
.forecast_container {
display: flex;
width: 510px;
height: 130px;
margin-left: auto;
margin-right: auto;
align-items: center;
text-align: center;
transition: transform 250ms;
}
.forecast_slider {
background-color: black;
color: white;
overflow: hidden;
float: right;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="app"></div>