React dnd drag item different from actual item - react-dnd

I try to dnd items from a list to a bucket.
The items have id, title, description
Problem:
When dragging the item labelled value: 1, title: foo , description: bar, randomly another item from the list are selected instead.
Cards List
value: 1, title: foo , description: bar
value: a, title: aaa , description: AAA
value: x, title: xxx , description: XXX
value: y, title: yyy , description: YYY
const FunctionCard = props => {
const { value, title, description} = props
const [{ isDragging }, drag] = useDrag(() => ({
type: "Card",
item: () => { console.log('item X selected', value, title, description); return ({ id:value })},
collect: (monitor) => {
console.log("collector drags item X", monitor.getItem());
return ({
isDragging: monitor.isDragging(),
handlerId: monitor.getHandlerId()
})}
}));
...

It is possible to assign dependencies to the hooks useDrag, useDrop (see github issue)
const FunctionCard = props => {
const { value, title, description} = props
const [{ isDragging }, drag] = useDrag(() => ({
type: "Card",
item: () => { console.log('item X selected', value, title, description); return ({ id:value })},
collect: (monitor) => {
console.log("collector drags item X", monitor.getItem());
return ({
isDragging: monitor.isDragging(),
handlerId: monitor.getHandlerId()
})}
}), [value, title, description]);
...

Related

React native Switch is not working for multiple fields correctly?

React-native switch toggle is not working even though i have set value for each feild separately.Also Its setting value correctly but toggle switch is not reflecting that.I want if user selects 2 field's the switch button should be enabled for that particular field's and others will be disabled.
const SystemInformation = props => {
const [isEnabled, setIsEnabled] = useState(false);
const [selectedFeild, setSelectedFeild] = useState([
{ id: 1, text: "Entry", toggle: false },
{ id: 2, text: "Exit", toggle: false },
{ id: 3, text: "Stay", toggle: false }
]);
const toggleSwitch = type => {
setSelectedFeild(type);
setIsEnabled(previousState => !previousState);
};
const renderWordList = () => {
const wordList = selectedFeild.map((word, i, wordArray) => (
<View key={word.id} style={styles.wordsContainer}>
<TextView>{word.text}</TextView>
<Switch
style={styles.pilgrimsWordSwitch}
onValueChange={toggleValue => {
wordArray[i].toggle = toggleValue;
setSelectedFeild(wordArray);
}}
value={word.toggle}
/>
</View>
));
return wordList;
};
return <View style={styles.container}>{renderWordList()}</View>;
};
export default SystemInformation;
Any lead will be appreciated what i am doing wrong ?

React-admin SelectInput occurs out of range warning

I have SelectInput inside of ReferenceInput
As you can see below,
This is workaround version of code. the selection shows right data and it parses as I expected, however, a out-of-range value **[object Object]** is show. (please see the reference image below)
This is a code snippet of SelectInput component
const AddressSelectInput: FC<AddressSelectInputProps> = (
{
customerId,
source,
...props
}
) => {
const classes = useStyles()
const [choices, setChoices] = useState<InputSourceProps[] | undefined>()
// sorting data from props
useEffect(() => {
if (props.choices) {
const result: InputSourceProps[] | undefined = props.choices?.find(
item => item._id === customerId
)?.addresses?.map((item: UserAddress) => {
let res: InputSourceProps;
res = {
name: item.label,
description: item.place.description,
postalCode: item.place.postalCode,
location: {
lat: item.place.location.lat,
lng: item.place.location.lng
}
}
return res;
})
setChoices(result)
}
}, [props.choices, customerId])
if (!choices) {
return null
}
const optionRenderer = (choice: Place) => `${choice.name} - ${choice.description}`;
return (
<SelectInput
className={classes.selectInputStyle}
label="Addresses suggestion"
choices={choices}
source={source}
optionText={optionRenderer}
optionValue={'name'}
defaultValue=''
parse={(name: string) => choices.find(c => c.name === name)}
/>
)
}
this is parent component of SelectInput:
const RideReferenceAddressInput: FC<RideReferenceInputProps> = ({
source,
label,
customerId,
}) => {
const filterToQuery = (customerId: string) => (filter: string) => ({
$search: filter,
_id: customerId
})
return (
<ReferenceInput
reference="users"
source={source}
filterToQuery={filterToQuery(customerId)}
>
<AddressSelectInput source={source} label={label} customerId={customerId} />
</ReferenceInput>
)
}
Could anyone can help to remove the warning? and why this is warning shows?
Thank you all in advance!

`react-native-dropdown-picker` not selecting default value for multiSelect, if list item having selected:true {label:"A", value:1, selected:true}

I am trying to use multiselect feature of react-native-dropdown-picker which is working fine for selecting item, I can select multiple Items and can get its values too, but my problem is I am not able to show defaultValue on screen load.
I am fetching data from server and then trying to show on dropdown-picker
const AccountSelection = (props) => {
const [accountId, setAccount] = useState([])
const [accountList, setAccountList] = useState([])
const [defaultAccount, setDefaultAccount] = useState([])
useEffect(() => {
getAccounts()
}, [])
const getAccounts = () => {
axiosConfig.get('/accounts')
.then((response) => {
if (response.status == 200) {
const accountData = response.data.payload.data
const accountNames = accountData.map((item) => ({ label: item.name, value: item.id, selected: item.id == store.usersDefaultValues.account_id ? true : false }))
setAccountList(accountNames)
setDefaultAccount(accountNames.find(item => item.selected == true ? item.value : null))
}
}
})
.catch((error) => {
console.log("axios error", error);
})
}
return (
<View>
<DropDownPicker
placeholder="Select Account"
value={accountId}
items={accountList}
onChangeItem={(val) => setAccountId(val)}
defaultValue={defaultAccount}
multiple={true}
activeItemStyle={{ backgroundColor: '#F5CCF8' }}
></DropDownPicker>
</View>
)
}
On screen Load I am getting blank dropdown-picker, where it should show 1 Item Selected.
In DropDownPickerProps in react-native-dropdown-picker optional selected key is available but it is not working
items: {
label: any;
value: any;
icon?: () => JSX.Element;
hidden?: boolean;
disabled?: boolean;
selected?: boolean;
}[];
Please share if anyone have solution for this. Thank you.
The defaultValue attribute is not longer supported in react-native-dropdown-picker. If you want to select a default value, you simply need to set the 'value' variable to the default value's value.
You can read more in this issue: https://github.com/hossein-zare/react-native-dropdown-picker/issues/511#issuecomment-1049110163.

Smooth Picker scrollIndex showing error while scrolling

Tried example of "react-native-smooth-picker#1.1.3" to implement smooth scroll when on scrolling found handleChange method throws error which is,
TypeError: refPicker.current.scrollToIndex is not a function. (In 'refPicker.current.scrollToIndex({animated: false,index: index,viewOffset: -30})','refPicker.current.scrollToIndex' is undefined).
Also when scrolling values not properly selecting and set in to useState by index. Please suggest what is the issue here and how to fix it.
Here is the smooth picker code,
...
import SmoothPicker from "react-native-smooth-picker";
const opacities = {
0: 1,
1: 1,
2: 0.6,
3: 0.3,
4: 0.1,
};
const sizeText = {
0: 20,
1: 15,
2: 10,
};
const ItemToRender = ({item, index}, indexSelected, vertical) => {
const selected = index === indexSelected;
const gap = Math.abs(index - indexSelected);
let opacity = opacities[gap];
if (gap > 3) {
opacity = opacities[4];
}
let fontSize = sizeText[gap];
if (gap > 1) {
fontSize = sizeText[2];
}
return ;
};
export default function SmoothPickerScreen({ navigation }) {
const [ selected, setSelected ] = React.useState(1);
const [value, setValue] = React.useState(null);
const [dataRows, setdataRows] = React.useState([]);
const data = [{name: 'A1',id:1},{name: 'A2',id:2}, {name: 'A2',id:3}, {name: 'A4',id:4}, {name: 'A5',id:5}, {name: 'A6',id:6}, {name: 'A7',id:7}, {name: 'A8',id:8}, {name: 'A9',id:9}, {name: 'A10',id:10}];
React.useEffect(() => {
(async () => {
setdataRows(data);
})();
}, []);
function handleChange(index) {
// console.log(index, refPicker);
setSelected(index);
refPicker.current.scrollToIndex({
animated: false,
index: index,
viewOffset: -30,
});
}
return (
{}}
keyExtractor={(_, index) => index.toString()}
showsVerticalScrollIndicator={false}
data={dataRows.map((o)=> {
// let obj;
return o.name
})}
// data={Array.from({ length: 16 }, (_, i) => i)}
scrollAnimation
onSelected={({ item, index }) => {
let find = dataRows.find(o => o.name === item)
// console.log('in scroll',item,index, find)
setValue(find.id)
handleChange(index)
}}
renderItem={option => ItemToRender(option, selected, true)}
magnet
/>
)
}

React native how to apply pagination and loadmore to each specific tab separately?

so i currently have a screen with a horizontal scroll view that contains my category tabs. When a tab is pressed, a flatlist is rendered below with all the posts specific for that category (this part is working correctly).
When the screen initially loads the first tab is selected by default and all the posts for that tab are rendered below.
Now, i have applied pagination in my backend and when i tested it on postman it is working.
My problem is:
eg. if i select tab 1, the first page (page=0) posts get rendered then when i scroll down, the page count increases to 2 but no posts get rendered. Also, then when i select tab 2, the page count doesnt reset back 0 it continues from where it left off in tab 1.
in tab 1 if i keep scrolling down to page 10, then i select tab 2.
What i want is the page count in tab 2 to start at 0.
what is happening the page count in tab 2 starts at 10.
Here is my code:
const getCategoryPostsAPI = (id,page)=>client.get(`/categories/${id}?page=${page}`)
function tabScreen({ navigation,route }) {
const [posts, setPosts] = useState([]);
const [error, setError] = useState(false);
const [loading, setLoading] = useState(false);
const[page,setPage]=useState(0);
const loadPosts = async (id) => {
setLoading(true);
const response = await getCategoryPostsAPI(id,page) //API call
setLoading(false);
if(refreshing) setRefreshing(false);
if (!response.ok) return setError(true);
setError(false);
if(page===0){
setPosts(response.data)
}else{
setPosts([...posts,...response.data]);
}};
useEffect(() => {
loadPosts(1,page);
}, [page]);
const categories = [
{
label: "Sports",
id: 1,
},
{
label: "Fashion",
id: 2,
},
{
label: "News",
id: 3,
},
{
label: "Cooking",
id: 4,
},
{
label: "Education",
id: 5,
}]
const handleLoadMore = ()=>{
setPage(page+1);
}
const[label,setLabel]=useState('Sports')
const setLabelFilter=label=>{
setLabel(label)
}
const [currentCategoryId, setCurrentCategoryId] = useState()
const toggleBrands = (categoryId) => {
setCurrentCategoryId(categoryId)
setLabel(label)
};
return (
<ScrollView
horizontal
showsHorizontalScrollIndicator={false}
>
{categories.map(e=>(
<TouchableOpacity
key={e.id}
onPress={()=>{toggleBrands(e.id),
setLabelFilter(e.label),
loadPosts(id=e.id),
setPage(0) // here i am trying to set the page to 0 on tab click
but it is not working
}}
selected={e.id === currentCategoryId}
>
<Text>{e.label}</Text>
</TouchableOpacity>
))}
</ScrollView>
<FlatList
data={currentCategoryId ? posts.filter(post=>post.categoryId===currentCategoryId
):posts.filter(post=>post.categoryId===1)}
keyExtractor={(post) => post.id.toString()}
renderItem={({ item,index }) => (
<Card
title={item.title}
subTitle={item.subTitle}
onPress={() => navigation.navigate(routes.POST_DETAILS, {post:item,index})}
/>
onEndReached={handleLoadMore}
onEndReachedThreshold={0.000001}
initialNumToRender={10}
)}
/>
I think i implemented my pagination wrong hence why my handleloadmore does not work because i have used the same handleloadmore in different screens and it is working.
I'm guessing you want the page to be reset to 0 when you click on another category and you want to paginate through the data when scrolling through a single category. If so, try this
const getCategoryPostsAPI = (id, page) => client.get(`/categories/${id}?page=${page}`);
const categories = [
{
label: "Sports",
id: 1,
},
{
label: "Fashion",
id: 2,
},
{
label: "News",
id: 3,
},
{
label: "Cooking",
id: 4,
},
{
label: "Education",
id: 5,
}
];
function tabScreen({ navigation, route }) {
const [posts, setPosts] = useState([]);
const [error, setError] = useState(false);
const [loading, setLoading] = useState(false);
const [page, setPage] = useState(0);
const [label, setLabel] = useState(categories[0]?.label);
const [currentCategoryId, setCurrentCategoryId] = useState(1);
const loadPosts = async (id, page = 0) => {
setLoading(true);
const response = await getCategoryPostsAPI(id, page)
setLoading(false);
if (refreshing) setRefreshing(false);
if (!response.ok) return setError(true);
setError(false);
if (page === 0) {
setPosts(response.data)
} else {
setPosts([...posts, ...response.data]);
}
};
useEffect(() => {
if (page > 0)
loadPosts(currentCategoryId, page);
}, [page]);
useEffect(() => {
setPage(0);
loadPosts(currentCategoryId, 0);
}, [currentCategoryId])
const handleLoadMore = () => {
setPage(page + 1);
};
const setLabelFilter = label => {
setLabel(label);
};
const toggleBrands = (categoryId) => {
setCurrentCategoryId(categoryId);
};
const postsToBeDisplayed = () => posts.filter(post => post.categoryId === currentCategoryId);
return (
<>
<ScrollView
horizontal
showsHorizontalScrollIndicator={false}
>
{categories.map(e => (
<TouchableOpacity
key={e.id}
onPress={() => {
toggleBrands(e.id);
setLabelFilter(e.label);
}}
selected={e.id === currentCategoryId}
>
<Text>{e.label}</Text>
</TouchableOpacity>
))}
</ScrollView>
<FlatList
data={postsToBeDisplayed()}
renderItem={({ item, index }) => (
<Card
title={item.title}
subTitle={item.subTitle}
onPress={() => navigation.navigate(routes.POST_DETAILS, { post: item, index })}
/>
)}
onEndReached={handleLoadMore}
onEndReachedThreshold={0.000001}
initialNumToRender={10}
keyExtractor={(post) => post.id.toString()}
/>
</>
)
};
However, if you want to implement the tab feature, I would recommend using react-native-tab-view. This will make the whole process a lot easier.