反应 useState 选项值比 onChange 选择落后 1 步 [英] React useState option value 1 step behind onChange selection

查看:53
本文介绍了反应 useState 选项值比 onChange 选择落后 1 步的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

size.value 状态是 _updateData 函数触发 的起始 defaultValue 选项为All",locations 为空...该选项更改为Medium",locations 为All"...选项更改为Large",locations 为Medium"...等等.最初,我希望 _updateData 函数在选择了All"的情况下运行 onload 也不起作用,它会抛出错误无法读取 setSize({value: event.target.value}).我在这里做错了什么?谢谢您的帮助.

const Map = () =>{const [viewport, setViewport] = useState({经度:-98.58,纬度:39.83,缩放:3.5})const [locations, setLocations] = useState([])const [geojson, setGeojson] = useState(null)const [size, setSize] = useState({value: "All"})useEffect(() => {设置位置(地理数据)_updateData()}, []);const _updateViewport = 视口 =>{设置视口(视口)}const _updateData = 事件 =>{setSize({value: event.target.value})const tempLocations = [];location.forEach(function(res) {if (size.value === "All") {tempLocations.push(res);} else if (res.Size === size.value) {tempLocations.push(res);}});变量数据 = {...};setGeojson(数据);}返回 (<ReactMapGL{...视口}onViewportChange={_updateViewport}宽度="100%"高度="100%"地图样式={地图样式}mapboxApiAccessToken={TOKEN}><Source id="my-data" type="geojson" data={geojson}><图层{...图标}/></来源><div style={navStyle}><NavigationControl onViewportChange={_updateViewport}/><select onChange={_updateData} defaultValue={size}><option value="All">All</option><option value="Large">Large</option><option value="Medium">Medium</option><option value="Small">Small</option><option value="Very Small">Very Small</option></选择>

</ReactMapGL>);}导出默认地图;

解决方案

是的,您正在挂载 useEffect 钩子中调用 select 的 onChange 处理程序,而没有事件对象取消引用 target 属性.我会分解出 updateData 代码的其余部分,以便您可以使用初始状态值调用它.这将允许您使用初始大小状态日期更新安装位置详细信息选择的 onChange 将保持原样.

注意:您应该注意状态更新要到下一个渲染周期才会生效,因此在您的代码中,您使用新值调用 setSize 但继续处理定位当前大小值,所以需要转发当前值.

const Map = () =>{const [viewport, setViewport] = useState({经度:-98.58,纬度:39.83,缩放:3.5})const [locations, setLocations] = useState([])const [geojson, setGeojson] = useState(null)const [size, setSize] = useState({value: "All"})//这里的初始大小状态useEffect(() => {设置位置(地理数据);更新位置数据(大小.值);//使用初始大小状态值在 mount 上调用位置更新器}, []);const _updateViewport = 视口 =>{设置视口(视口)}const _updateData = 事件 =>{setSize({value: event.target.value})updateLocationData(event.target.value);//转发当前大小值}const updateLocationData = (sizeValue) =>{//转发大小值const tempLocations = [];location.forEach(function(res) {if (sizeValue === "All") {//转发大小值进行比较tempLocations.push(res);} else if (res.Size === sizeValue) {//转发大小值进行比较tempLocations.push(res);}});变量数据 = {...};setGeojson(数据);};返回 (<ReactMapGL{...视口}onViewportChange={_updateViewport}宽度=100%"高度=100%"地图样式={地图样式}mapboxApiAccessToken={TOKEN}><Source id="my-data";类型=geojson";数据={geojson}><图层{...icon}/></来源><div style={navStyle}><NavigationControl onViewportChange={_updateViewport}/><select onChange={_updateData} defaultValue={size.value}>//需要解包实际大小值<option value=All">All</option><option value=Large">Large</option><option value=Medium">Medium</option><option value=Small">Small</option><选项值=非常小">非常小</option></选择>

</ReactMapGL>);}导出默认地图;

The size.value state is one option behind when the _updateData function triggers onChange of the <select>. For example, Let's say the starting defaultValue option of <select> is "All", locations is empty...the option is changed to "Medium", locations is "All"...the option is changed to "Large", locations is "Medium"...and so on. Initially I want the _updateData function to run onload with "All" selected which is not working either, it throws the error Cannot read property 'target' of undefined on setSize({value: event.target.value}). What am I doing wrong here? Thanks for the help.

const Map = () => {
    const [viewport, setViewport] = useState({longitude: -98.58, latitude: 39.83, zoom: 3.5})
    const [locations, setLocations] = useState([])
    const [geojson, setGeojson] = useState(null)
    const [size, setSize] = useState({value: "All"})

    useEffect(() => {
        setLocations(geodata)
        _updateData()
    }, []);

    const _updateViewport = viewport => {
        setViewport(viewport)
    }

    const _updateData = event => {
        setSize({value: event.target.value})
        const tempLocations = [];
        locations.forEach(function(res) {
            if (size.value === "All") {
                tempLocations.push(res);
            } else if (res.Size === size.value) {
                tempLocations.push(res);
            }
        });
        var data = {
            ...
        };
        setGeojson(data);
    }

    return (
        <ReactMapGL
            {...viewport}
            onViewportChange={_updateViewport}
            width="100%"
            height="100%"
            mapStyle={mapStyle}
            mapboxApiAccessToken={TOKEN}>
            <Source id="my-data" type="geojson" data={geojson}>
                <Layer {...icon} />
            </Source>
            <div style={navStyle}>
                <NavigationControl onViewportChange={_updateViewport} />
                <select onChange={_updateData} defaultValue={size}>
                    <option value="All">All</option>
                    <option value="Large">Large</option>
                    <option value="Medium">Medium</option>
                    <option value="Small">Small</option>
                    <option value="Very Small">Very Small</option>
                </select>
            </div>
        </ReactMapGL>
    );
}

export default Map;

解决方案

Yes, you are calling your select's onChange handler in the mounting useEffect hook with no event object to dereference a target property. I would factor out the rest of the updateData code so you can call it with the initial state value. This will allow you to update location details on mount using the initial size state date AND the select's onChange will remain as it was previously.

NOTE: You should note that updates to state won't take effect until the next render cycle, so in your code you call setSize with the new value but continue processing locations the current size value, so you need to forward the current value.

const Map = () => {
    const [viewport, setViewport] = useState({longitude: -98.58, latitude: 39.83, zoom: 3.5})
    const [locations, setLocations] = useState([])
    const [geojson, setGeojson] = useState(null)
    const [size, setSize] = useState({value: "All"}) // initial size state here

    useEffect(() => {
        setLocations(geodata);
        updateLocationData(size.value); // call the location updater on mount with the initial size state value
    }, []);

    const _updateViewport = viewport => {
        setViewport(viewport)
    }

    const _updateData = event => {
        setSize({value: event.target.value})
        updateLocationData(event.target.value); // forward current size value
    }

    const updateLocationData = (sizeValue) => { // forwarded size value
        const tempLocations = [];
        locations.forEach(function(res) {
            if (sizeValue === "All") { // forwarded size value for comparison
                tempLocations.push(res);
            } else if (res.Size === sizeValue) { // forwarded size value for comparison
                tempLocations.push(res);
            }
        });
        var data = {
            ...
        };
        setGeojson(data);
    };

    return (
        <ReactMapGL
            {...viewport}
            onViewportChange={_updateViewport}
            width="100%"
            height="100%"
            mapStyle={mapStyle}
            mapboxApiAccessToken={TOKEN}>
            <Source id="my-data" type="geojson" data={geojson}>
                <Layer {...icon} />
            </Source>
            <div style={navStyle}>
                <NavigationControl onViewportChange={_updateViewport} />
                <select onChange={_updateData} defaultValue={size.value}> // need to unpack the actual size value
                    <option value="All">All</option>
                    <option value="Large">Large</option>
                    <option value="Medium">Medium</option>
                    <option value="Small">Small</option>
                    <option value="Very Small">Very Small</option>
                </select>
            </div>
        </ReactMapGL>
    );
}

export default Map;

这篇关于反应 useState 选项值比 onChange 选择落后 1 步的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
其他开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆