预先填充的滑块值,总是跳回到预先填充的api数据的默认状态



你好,我有一个预填充的滑块,用于评分,我用API的数据预填充它,如果用户滑动,我想更新API数据库。一切都很好,只是滑块总是通过useEffect跳回到预填充的值。如何更改状态,使用户的值优先于预填充的值?

这是我的代码:

const [ user ] = useContext(Context);
const location = useLocation();
const { pathname } = location;
const splitLocation = pathname.split("/");
const movieId = splitLocation[2];
const [ MovieResults, setMovieResults ] = useState([]);
const [ value, setValue ] = useState(5);
useEffect(() => {
let isMounted = true; 

fetch(`${API_URL}account/xxxxxxxx/rated/movies?api_key=${API_KEY}&session_id=${user.sessionId}&sort_by=created_at.desc`)
.then(res => res.json())
.then(data => isMounted ? setMovieResults(data.results) : null)
.then(isMounted ? MovieResults.forEach((arrayItem) => { 
if(arrayItem.id.toString() === movieId.toString()) {
setValue(arrayItem.rating);  
}
}) : null)

return () => { isMounted = false };
},[user.sessionId, MovieResults, movieId]);
const changeSlider = (e) => {
// This value should override the default value from the api 
setValue(e.currentTarget.value);
};
return (
<div>
<input 
type="range" 
min="1" 
max="10" 
className="rate-slider"
value={value} 
onChange={e => changeSlider(e)}
/>
{value}
<p>
<button className="rate-button" onClick={() => callback(value)}>Rate</button>
</p>
</div>
)

感谢帮助,不胜感激。

我终于解决了这个问题。我需要根据用户滑动滑块的条件,让两个setValue中的一个优先于另一个。到目前为止,我还不知道useRef,有了这个钩子,我可以管理它。这是代码:

const [ user ] = useContext(Context);
const location = useLocation();
const { pathname } = location;
const splitLocation = pathname.split("/");
const movieId = splitLocation[2];
const [ MovieResults, setMovieResults ] = useState([]);
const [ value, setValue ] = useState(5);
const ref = useRef(0);
useEffect(() => {
let isMounted = true; 

fetch(`${API_URL}account/jensgeffken/rated/movies?api_key=${API_KEY}&session_id=${user.sessionId}&sort_by=created_at.desc`)
.then(res => res.json())
.then(data => isMounted ? setMovieResults(data.results) : null)
.then(isMounted ? MovieResults.forEach((arrayItem) => { 
if(arrayItem.id.toString() === movieId.toString()) {

//console.log(ref.current)
if(ref.current === 0) {
setValue(arrayItem.rating);
}  
}
}) : null)

return () => { isMounted = false };
},[user.sessionId, MovieResults, movieId]);
const handleSlide = (e) => {
ref.current = e.currentTarget.value
setValue(ref.current);
}

return (
<div>
<input 
type="range" 
min="1" 
max="10" 
className="rate-slider"
value={value} 
onChange={e => handleSlide(e)}
/>
{value}
<p>
<button className="rate-button" onClick={() => callback(value)}>Rate</button>
</p>
</div>
)

按照您的一般方法,这对我来说似乎很好:

const fetch = () => new Promise(resolve => setTimeout(() => 
resolve({json: () => ({rating: 4})})
, 1000));
const App = () => {
const [sliderVal, setSliderVal] = React.useState(0);
const [loading, setLoading] = React.useState(true);

React.useEffect(() => {
fetch("foo")
.then(res => res.json())
.then(data => {
setLoading(false);
setSliderVal(data.rating);
});
}, []);

const handleSliderChange = evt => {
setSliderVal(evt.target.value);
};
return (
<div>    
{loading 
? <p>loading...</p>
: <div>
<input
type="range" 
min="1" 
max="10" 
value={sliderVal}
onChange={handleSliderChange}
/>
{sliderVal}
</div>
}
</div>
);
};
ReactDOM.createRoot(document.querySelector("#app"))
.render(<App />);
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<div id="app"></div>

最新更新