Я новичок в React Native и пытаюсь создать приложение с операцией CRUD и RESTful API, но я застрял в UPDATE/PUT. Может ли кто-нибудь помочь в этом вопросе?? Ниже приведены коды внешнего интерфейса + внутреннего интерфейса:
Бэкэнд-сторона
// update data by id
router.put('/:id', validate, (req, res) => {
const bookId = req.params.id
const errors = validationResult(req)
if (!errors.isEmpty()){
return res.status(422).send({errors: errors.array()})
}
Book.findById(bookId)
.then(book => {
book.bookTitle = req.body.bookTitle,
book.ImgURL = req.body.ImgURL,
book.bookDescription = req.body.bookDescription,
book.bookAuthor = req.body.bookAuthor,
book.bookPrice = req.body.bookPrice,
book.bookTypes = req.body.bookTypes,
book.bookYear = req.body.bookYear,
book.bookRating = req.body.bookRating,
book.bookPages = req.body.bookPages
return book.save()
})
.then(result => res.send(result))
.catch(errors => console.info(errors))
})
Результат в POSTMAN, я изменил название с как заваривать -> как заваривать как профессионал
ReduxAction.js
export const editBook = ({id, bookTitle, ImgURL, bookDescription, bookAuthor, bookPrice, bookTypes, bookYear, bookRating, bookPages}) => {
return async dispatch => {
const response = await fetch(`http://localhost:3000/api/books/${id}`, {
method: 'PUT',
body: JSON.stringify({id, bookTitle, ImgURL, bookDescription, bookAuthor, bookPrice, bookTypes, bookYear, bookRating, bookPages})
})
const responseData = await response.json()
dispatch({
type: EDIT_BOOKS,
payload: responseData
})
}
}
EditScreen.js
import React, {useState, useEffect} from 'react'
import { StyleSheet, Text, View, ScrollView, TextInput, Button, KeyboardAvoidingView, Alert,
ActivityIndicator } from 'react-native'
import { useDispatch, useSelector } from 'react-redux'
import * as bookAction from '../redux/actions/bookAction'
import { Formik } from 'formik'
import * as Yup from 'yup'
import DropDownPicker from 'react-native-dropdown-picker'
const formSchema = Yup.object({
bookTitle: Yup.string().required('*required').min(5, '*must be between 5 to 50 characters').max(50, '*must be between 5 to 50 characters'),
ImgURL: Yup.string().required('*required'),
bookDescription: Yup.string().required('*required').min(30, '*must be at least 30 characters'),
bookAuthor: Yup.string().required('*required'),
bookPrice: Yup.number().required('*required'),
bookTypes: Yup.string().required('*required'),
bookYear: Yup.number().required('*required'),
bookRating: Yup.number().required('*required'),
bookPages: Yup.number().required('*required')
})
const AddBookScreen = props => {
const {id} = props.route.params
const book = useSelector(state => state.book.books.find(book => book._id === id))
const [isLoading, setIsLoading] = useState(false)
if (isLoading) {
return (
<View style = {styles.centered}>
<ActivityIndicator size = "large" />
</View>
)
}
const dispatch = useDispatch()
return (
<KeyboardAvoidingView
behavior = "padding"
keyboardVerticalOffset = {100}
style = {{flex: 1}}>
<ScrollView>
<Formik
initialValues = {{
id: id,
bookTitle: book.bookTitle,
ImgURL: book.ImgURL,
bookDescription: book.bookDescription,
bookAuthor: book.bookAuthor,
bookPrice: book.bookPrice.toString(),
bookTypes: book.bookTypes,
bookYear: book.bookYear.toString(),
bookRating: book.bookRating.toString(),
bookPages: book.bookPages.toString()
}}
validationSchema = {formSchema}
onSubmit = {(values) => {
console.info(values)
setIsLoading(true)
dispatch(bookAction.editBook(values))
.then(() => {
setIsLoading(false)
Alert.alert('book edited successfrully')
})
.catch(() => {
setIsLoading(false)
Alert.alert('an error occurred, please try again!')
})
}}>
{(props) =>
(
<View style = {styles.form}>
<View style = {styles.formGroup}>
<Text style = {styles.label}>Book Title</Text>
<TextInput
style = {styles.input}
onChangeText = {props.handleChangeEvent('bookTitle')}
onBlur = {props.handleBlur('bookTitle')}
value = {props.values.bookTitle}
/>
<Text style = {styles.error}>{props.touched.bookTitle && props.errors.bookTitle}</Text>
</View>
<View style = {styles.formGroup}>
<Text style = {styles.label}>Imgae URL</Text>
<TextInput
style = {styles.input}
onChangeText = {props.handleChangeEvent('ImgURL')}
onBlur = {props.handleBlur('ImgURL')}
value = {props.values.ImgURL}
/>
<Text style = {styles.error}>{props.touched.ImgURL && props.errors.ImgURL}</Text>
</View>
<View style = {styles.formGroup}>
<Text style = {styles.label}>Book Description</Text>
<TextInput
style = {styles.input}
onChangeText = {props.handleChangeEvent('bookDescription')}
onBlur = {props.handleBlur('bookDescription')}
value = {props.values.bookDescription}
/>
<Text style = {styles.error}>{props.touched.bookDescription && props.errors.bookDescription}</Text>
</View>
<View style = {styles.formGroup}>
<Text style = {styles.label}>Book Author</Text>
<TextInput
style = {styles.input}
onChangeText = {props.handleChangeEvent('bookAuthor')}
onBlur = {props.handleBlur('bookAuthor')}
value = {props.values.bookAuthor}
/>
<Text style = {styles.error}>{props.touched.bookAuthor && props.errors.bookAuthor}</Text>
</View>
<View style = {styles.formGroup}>
<Text style = {styles.label}>Book Price</Text>
<TextInput
style = {styles.input}
onChangeText = {props.handleChangeEvent('bookPrice')}
onBlur = {props.handleBlur('bookPrice')}
value = {props.values.bookPrice}
keyboardType='numeric'
/>
<Text style = {styles.error}>{props.touched.bookPrice && props.errors.bookPrice}</Text>
</View>
<View style = {styles.formGroup}>
<Text style = {styles.label}>Book Types</Text>
<TextInput
style = {styles.input}
onChangeText = {props.handleChangeEvent('bookTypes')}
onBlur = {props.handleBlur('bookTypes')}
value = {props.values.bookTypes}
/>
<Text style = {styles.error}>{props.touched.bookTypes && props.errors.bookTypes}</Text>
</View>
<View style = {styles.formGroup}>
<Text style = {styles.label}>Book Year</Text>
<TextInput
style = {styles.input}
onChangeText = {props.handleChangeEvent('bookYear')}
onBlur = {props.handleBlur('bookYear')}
value = {props.values.bookYear}
keyboardType='numeric'
/>
<Text style = {styles.error}>{props.touched.bookYear && props.errors.bookYear}</Text>
</View>
<View style = {styles.formGroup}>
<Text style = {styles.label}>Book Rating</Text>
<TextInput
style = {styles.input}
onChangeText = {props.handleChangeEvent('bookRating')}
onBlur = {props.handleBlur('bookRating')}
value = {props.values.bookRating}
keyboardType='numeric'
/>
<Text style = {styles.error}>{props.touched.bookRating && props.errors.bookRating}</Text>
</View>
<View style = {styles.formGroup}>
<Text style = {styles.label}>Book Pages</Text>
<TextInput
style = {styles.input}
onChangeText = {props.handleChangeEvent('bookPages')}
onBlur = {props.handleBlur('bookPages')}
value = {props.values.bookPages}
keyboardType='numeric'
/>
<Text style = {styles.error}>{props.touched.bookPages && props.errors.bookPages}</Text>
</View>
<View style = {styles.buttonContainer}>
<Button title='save edit' onPress = {props.handleSubmit} color='steelblue' />
</View>
</View>
)}
</Formik>
</ScrollView>
</KeyboardAvoidingView>
)
}
export default AddBookScreen
const styles = StyleSheet.create({
form: {
backgroundColor: "#ffffff",
padding: 20,
borderRadius: 10,
},
formGroup: {
width: "100%",
},
label: {
marginVertical: 10,
},
input: {
paddingHorizontal: 2,
paddingVertical: 8,
borderBottomColor: "#ccc",
borderBottomWidth: 1,
},
buttonContainer: {
marginTop: 20,
},
error: {
color: 'red'
},
centered: {
flex: 1,
justifyContent: 'center',
alignItems: 'center'
}
})
Собственный отладчик React
Отредактировано
Устранить ошибку в отладчике, изменив ReduxReducer.js
case EDIT_BOOKS:
return {
...state,
books: state.books.map(book => action.payload.find(item => item.id === book._id) || book)
}
Ошибка ушла, но данные не обновились
Итак, я нашел решение своей проблемы, отредактировав ReduxReducer.js на
case EDIT_BOOKS:
return {
...state,
books: [...state.books]
}