我有一个从数组呈现的复选框列表UI。更新阵列后,复选框列表状态不会更新。
我将代码移动到映射列表的位置,但是它不会更改结果。不会发生DOM重新渲染,请参见下面的gif。
我一直在寻找周围的事物,但我发现已经报告了此问题,但是关于将list.map
代码移出其功能的解决方案对我不起作用。
您能给我建议一个解决方案吗? 这个问题的根源是什么?
import React,{ useState } from "react"
import
{
Box,
DropButton,
Grid,
Text,
Calendar,
RangeInput,
CheckBox
} from "grommet"
const CalButton = ( { label,onSelect } ) =>
{
return (
<DropButton
label={ label }
dropAlign={ { top: 'bottom',left: 'left' } }
margin="small"
dropContent={
<Box pad="medium" background="ligth-3" elevation="small">
<Calendar range size="medium" onSelect={ onSelect } />
</Box>
} />
)
}
const RangeButton = ( { label,value,onChange,min,max,step,unit,header } ) =>
{
return (
<DropButton
label={ value === null ? label : value + ' ' + unit }
dropAlign={ { top: 'bottom',left: 'left' } }
margin="small"
dropContent={
<Box pad="medium"
background="ligth-3"
elevation="small"
align="center"
>
<Text size="small">{ header }</Text>
<RangeInput
value={ value }
min={ min } max={ max }
onChange={ onChange }
step={ step }
/>
<Text weight="bold">{ value }</Text>
<Text weight="normal">{ unit }</Text>
</Box>
} />
)
}
const FeaturesButton = ( { label,features,onChange } ) =>
{
const FeaturesList = ( { features,onChange } ) => (
<>
{ features.map( ( item,idx ) => (
<CheckBox
key={ item.name }
label={ item.name }
checked={ item.checked }
onChange={ e => onChange( e,idx ) } />)
)
}
</>
)
return (
<DropButton
label={ label }
dropAlign={ { top: 'bottom',left: 'left' } }
margin="small"
dropContent={
<Box pad="medium"
background="ligth-3"
elevation="small"
align="start"
direction="column"
gap="small"
>
<FeaturesList
features={features}
onChange={onChange} />
</Box>
} />
)
}
const destApp = () =>
{
const [ windStrength,setWindStrength ] = useState( null )
const [ windFrequency,setWindFrequency ] = useState( null )
const [ cost,setCost ] = useState( null )
const date = new Date()
const [ month,setMonth ] = useState( date.getMonth() )
const [ listFeatures,setListFeatures ] = useState( [
{
name: 'Butter flat water',
checked: false,
},
{
name: 'Moderately flat water',
checked: false,
},
{
name: '1-2m Waves',
checked: false,
},
{
name: '2m+ Waves',
checked: false,
},
{
name: 'Beginer Friendly',
checked: false,
},
{
name: 'Kite-in-kite-out',
checked: false,
},
{
name: 'Nightlife',
checked: false,
}
] )
const months = [ 'January','February','March','April','May','June','July','August','September','October','November','December' ];
const updateFeaturesList = ( e,idx ) =>
{
listFeatures[ idx ].checked = e.target.checked
const newFeatures = listFeatures
setListFeatures( newFeatures )
console.log( "Updated features list",newFeatures,e.target.checked )
}
return (
<Grid rows={ [ "xsmall","fill" ] }
areas={ [ [ "filterBar" ],[ "results" ] ] }
gap="xxsmall">
<Box gridArea="filterBar"
direction="row-responsive"
gap="xsmall"
pad="xsmall"
justify="center" >
<CalButton label={ months[ month ].toLowerCase() } onSelect={ ( data ) => console.log( data ) } />
<RangeButton
label="wind strength"
header="What's your wind preference?"
min="15"
max="45"
unit="kts"
value={ windStrength }
step={ 1 }
onChange={ ( e ) =>
{
setWindStrength( e.target.value )
console.log( windStrength )
} } />
<RangeButton
label="wind frequency"
header="How often does your destination need to be windy?"
min="1"
max="7"
unit="days/week"
value={ windFrequency }
step={ 1 }
onChange={ ( e ) =>
{
setWindFrequency( e.target.value )
console.log( windFrequency )
} } />
<RangeButton
label="cost"
header="Average daily cost: 1 lunch, diner and doubble room at a midrange hotel?"
min="10"
max="400"
unit="€"
value={ cost }
step={ 1 }
onChange={ ( e ) =>
{
setCost( e.target.value )
console.log( cost )
} } />
<FeaturesButton
label="important features "
features={ listFeatures }
onChange={ updateFeaturesList }
/>
</Box>
<Box gridArea="results"
margin="">
Results go in here!
</Box>
</Grid>
)
}
export default destApp
答案 0 :(得分:1)
您正在updateFeaturesList
函数中改变原始状态。使用setState
的功能形式来更新您当前的功能列表:
const updateFeaturesList = (e, idx) => {
const { checked } = e.target;
setListFeatures(features => {
return features.map((feature, index) => {
if (id === index) {
feature = { ...feature, checked };
}
return feature;
});
});
};
还要注意,由于设置状态是异步的,因此在设置状态后立即调用console.log("Updated features list", newFeatures,e.target.checked)
不会显示更新后的状态。
答案 1 :(得分:1)
问题出在private class LineChartFormatter: NSObject, IAxisValueFormatter {
var labels: [String] = []
let dateFormatter = DateFormatter()
let dateShortFormatter = DateFormatter()
func stringForValue(_ value: Double, axis: AxisBase?) -> String {
if let date = dateFormatter.date(from:labels[Int(value)]) {
if value == 0 {
dateShortFormatter.dateFormat = "MMM dd"
return dateShortFormatter.string(from: date)
} else {
let prevDate = dateFormatter.date(from:labels[Int(value - 1)])
dateShortFormatter.dateFormat = "MMM"
if dateShortFormatter.string(from: date) != dateShortFormatter.string(from: prevDate!) {
dateShortFormatter.dateFormat = "MMM dd"
return dateShortFormatter.string(from: date)
} else {
dateShortFormatter.dateFormat = "dd"
return dateShortFormatter.string(from: date)
}
}
} else {
return labels[Int(value)]
}
}
init(labels: [String]) {
super.init()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss Z"
self.labels = labels
}}
中,您直接在此行updateFeaturesList
中对状态进行了更改,状态引用保持不变,因此react不知道是否应该重新呈现。
您可以做的就是在更改状态之前复制状态:
listFeatures[ idx ].checked = e.target.checked