React Native Calendars:如何仅更改议程中一项的背景?
React Native Calendars : How to change the background of only one item in an agenda?
我试图只更改此议程中一个项目的背景,但使用我的代码,当我单击一个项目时,它会更改所有项目的背景颜色,而不仅仅是我单击的项目的背景颜色:screen before clicking on item screen after clicking
问题在于只知道如何更改议程中一个项目的样式,而不是所有项目的样式。
这是我的代码:
import React, { useState } from 'react';
import {
StyleSheet,
Text,
View,
TouchableOpacity,
} from 'react-native';
import moment from 'moment';
import { Avatar, Card } from 'react-native-paper';
import {Agenda} from "react-native-calendars";
const timeToString = (time) => {
const date = new Date(time);
return date.toISOString().split('T')[0];
};
export default function calendarScreen () {
const [color, setColor] = useState(
{backgroundColor: 'white', backgroundColor2: 'white', texte: 'Disponible', pressed: false}
);
const changeColor = () => {
if (!color.pressed) {
setColor({backgroundColor: 'lightgreen', backgroundColor2: 'white', texte: 'Réservé', pressed: true})
} else {
setColor({backgroundColor: 'white', backgroundColor2: 'green', texte: 'Disponible', pressed: false})
}
};
const [items, setItems] = useState({});
const loadItems = (day) => {
setTimeout(() => {
for (let i = -15; i < 85; i++) {
const time = day.timestamp + i * 24 * 60 * 60 * 1000;
const strTime = timeToString(time);
if (!items[strTime]) {
items[strTime] = [];
const numItems = 1;
for (let j = 0; j < numItems; j++) {
items[strTime].push({
name: 'Disponible',
height: Math.max(50, Math.floor(Math.random() * 150)),
style: color.backgroundColor
});
}
}
}
const newItems = {};
Object.keys(items).forEach(key => {newItems[key] = items[key];});
setItems(newItems);
}, 1000);
};
const renderItem = (item, firstItemInDay) => {
return (
<TouchableOpacity style={{ marginTop: 17, marginRight: 10}} onPress={(changeColor)}>
<Card style={ { backgroundColor : color.backgroundColor }}>
<Card.Content>
<View style={{
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
}}>
<Text>{item.name}</Text>
<Avatar.Text label="J" />
</View>
</Card.Content>
</Card>
</TouchableOpacity>
)
};
return (
<View style={{flex:1}}>
<Agenda
items={items}
loadItemsForMonth={loadItems}
selected={'2020-09-23'}
renderItem={renderItem}
/>
</View>
)
}
非常感谢您的帮助
问题是颜色状态绑定到您正在渲染的每个项目。您正在渲染的每个项目都应该知道自己是否处于活动状态,即有自己的状态。
所以你可以这样做:
const activeItemText = 'Réservé';
const activeItemStyles = {
backgroundColor: 'lightgreen',
backgroundColor2: 'white',
};
const inactiveItemText = 'Disponible';
const inactiveItemStyles = {
backgroundColorPrimary: 'white',
backgroundColorSecondary: 'white',
};
const timeToString = (time) => {
const date = new Date(time);
return date.toISOString().split('T')[0];
};
const CalendarItem = ({item, firstItemInDay}) => {
const [active, setActive] = React.useState(false);
const changeColor = () => {
setActive(!active);
};
return (
<TouchableOpacity
style={{marginTop: 17, marginRight: 10}}
onPress={changeColor}>
<Card style={active ? activeItemStyles : inactiveItemStyles}>
<Card.Content>
<View
style={{
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
}}>
<Text>{active ? activeItemText : inactiveItemText}</Text>
<Avatar.Text label="J" />
</View>
</Card.Content>
</Card>
</TouchableOpacity>
);
};
const renderItem = (item, firstItemInDay) => {
return <CalendarItem item={item} firstItemInDay={firstItemInDay} />;
};
const App = () => {
const [items, setItems] = useState({});
const loadItems = (day) => {
setTimeout(() => {
for (let i = -15; i < 85; i++) {
const time = day.timestamp + i * 24 * 60 * 60 * 1000;
const strTime = timeToString(time);
if (!items[strTime]) {
items[strTime] = [];
const numItems = 1;
for (let j = 0; j < numItems; j++) {
items[strTime].push({
name: inactiveItemStyles.texte,
height: Math.max(50, Math.floor(Math.random() * 150)),
});
}
}
}
const newItems = {};
Object.keys(items).forEach((key) => {
newItems[key] = items[key];
});
setItems(newItems);
}, 1000);
};
return (
<View style={{flex: 1}}>
<Agenda
items={items}
loadItemsForMonth={loadItems}
selected={'2020-09-23'}
renderItem={renderItem}
/>
</View>
);
};
export default App;
进一步解释上述方法
我将样式和可能的文本值放在任何组件之外,并创建了一个自定义 CalendarItem
组件,该组件传递给您的 renderItem
函数。
因为 CalendarItem
是一个功能组件,它可以有自己的状态。在这个实例中,我们不必将整个对象保存在状态中,因为我们真正想知道的只是一个项目是否处于活动状态。我们可以在按下时更新 active
状态,然后根据您的活动和非活动样式和数据有条件地呈现 CalendarItem
。
我试图只更改此议程中一个项目的背景,但使用我的代码,当我单击一个项目时,它会更改所有项目的背景颜色,而不仅仅是我单击的项目的背景颜色:screen before clicking on item screen after clicking
问题在于只知道如何更改议程中一个项目的样式,而不是所有项目的样式。
这是我的代码:
import React, { useState } from 'react';
import {
StyleSheet,
Text,
View,
TouchableOpacity,
} from 'react-native';
import moment from 'moment';
import { Avatar, Card } from 'react-native-paper';
import {Agenda} from "react-native-calendars";
const timeToString = (time) => {
const date = new Date(time);
return date.toISOString().split('T')[0];
};
export default function calendarScreen () {
const [color, setColor] = useState(
{backgroundColor: 'white', backgroundColor2: 'white', texte: 'Disponible', pressed: false}
);
const changeColor = () => {
if (!color.pressed) {
setColor({backgroundColor: 'lightgreen', backgroundColor2: 'white', texte: 'Réservé', pressed: true})
} else {
setColor({backgroundColor: 'white', backgroundColor2: 'green', texte: 'Disponible', pressed: false})
}
};
const [items, setItems] = useState({});
const loadItems = (day) => {
setTimeout(() => {
for (let i = -15; i < 85; i++) {
const time = day.timestamp + i * 24 * 60 * 60 * 1000;
const strTime = timeToString(time);
if (!items[strTime]) {
items[strTime] = [];
const numItems = 1;
for (let j = 0; j < numItems; j++) {
items[strTime].push({
name: 'Disponible',
height: Math.max(50, Math.floor(Math.random() * 150)),
style: color.backgroundColor
});
}
}
}
const newItems = {};
Object.keys(items).forEach(key => {newItems[key] = items[key];});
setItems(newItems);
}, 1000);
};
const renderItem = (item, firstItemInDay) => {
return (
<TouchableOpacity style={{ marginTop: 17, marginRight: 10}} onPress={(changeColor)}>
<Card style={ { backgroundColor : color.backgroundColor }}>
<Card.Content>
<View style={{
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
}}>
<Text>{item.name}</Text>
<Avatar.Text label="J" />
</View>
</Card.Content>
</Card>
</TouchableOpacity>
)
};
return (
<View style={{flex:1}}>
<Agenda
items={items}
loadItemsForMonth={loadItems}
selected={'2020-09-23'}
renderItem={renderItem}
/>
</View>
)
}
非常感谢您的帮助
问题是颜色状态绑定到您正在渲染的每个项目。您正在渲染的每个项目都应该知道自己是否处于活动状态,即有自己的状态。
所以你可以这样做:
const activeItemText = 'Réservé';
const activeItemStyles = {
backgroundColor: 'lightgreen',
backgroundColor2: 'white',
};
const inactiveItemText = 'Disponible';
const inactiveItemStyles = {
backgroundColorPrimary: 'white',
backgroundColorSecondary: 'white',
};
const timeToString = (time) => {
const date = new Date(time);
return date.toISOString().split('T')[0];
};
const CalendarItem = ({item, firstItemInDay}) => {
const [active, setActive] = React.useState(false);
const changeColor = () => {
setActive(!active);
};
return (
<TouchableOpacity
style={{marginTop: 17, marginRight: 10}}
onPress={changeColor}>
<Card style={active ? activeItemStyles : inactiveItemStyles}>
<Card.Content>
<View
style={{
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
}}>
<Text>{active ? activeItemText : inactiveItemText}</Text>
<Avatar.Text label="J" />
</View>
</Card.Content>
</Card>
</TouchableOpacity>
);
};
const renderItem = (item, firstItemInDay) => {
return <CalendarItem item={item} firstItemInDay={firstItemInDay} />;
};
const App = () => {
const [items, setItems] = useState({});
const loadItems = (day) => {
setTimeout(() => {
for (let i = -15; i < 85; i++) {
const time = day.timestamp + i * 24 * 60 * 60 * 1000;
const strTime = timeToString(time);
if (!items[strTime]) {
items[strTime] = [];
const numItems = 1;
for (let j = 0; j < numItems; j++) {
items[strTime].push({
name: inactiveItemStyles.texte,
height: Math.max(50, Math.floor(Math.random() * 150)),
});
}
}
}
const newItems = {};
Object.keys(items).forEach((key) => {
newItems[key] = items[key];
});
setItems(newItems);
}, 1000);
};
return (
<View style={{flex: 1}}>
<Agenda
items={items}
loadItemsForMonth={loadItems}
selected={'2020-09-23'}
renderItem={renderItem}
/>
</View>
);
};
export default App;
进一步解释上述方法
我将样式和可能的文本值放在任何组件之外,并创建了一个自定义 CalendarItem
组件,该组件传递给您的 renderItem
函数。
因为 CalendarItem
是一个功能组件,它可以有自己的状态。在这个实例中,我们不必将整个对象保存在状态中,因为我们真正想知道的只是一个项目是否处于活动状态。我们可以在按下时更新 active
状态,然后根据您的活动和非活动样式和数据有条件地呈现 CalendarItem
。