React-Redux : ошибка типа: props.onSubmit не является функцией

#reactjs #redux

#reactjs #redux

Вопрос:

Я пытаюсь вызвать создателя действия добавить продукт из компонента продукта формы. Я не понимаю, где я ошибаюсь. Может кто-нибудь, пожалуйста, помочь мне решить эту проблему? Я новичок в redux, так как я могу добиться решения, чтобы при заполнении формы продукт должен быть добавлен и вызывается создатель действия.

Вот код :


FormProduct.js

 import { makeStyles, TextField, Grid } from '@material-ui/core'
import React, { useState, useEffect } from 'react'
import { useForm, Form } from '../useForm'
import Input from '../../components/controls/Input'
import Select from '../controls/Select'
import * as productService from '../../services/productService'
import DatePicker from '../controls/DatePicker'
import Button from '../controls/Button'

const initialValues = {
    id: 0,
    name: '',
    description: '',
    quantity: '',
    price: '',
    dop: new Date(),
    category: ''
}

const FormProduct = (props) => {
    const validate = (fieldValues = values) => {
        let errors = { }
        if ('name' in fieldValues)
            errors.name = values.name ? '' : 'This field is required'
        if ('description' in fieldValues)
            errors.description = values.description ? '' : 'This field is required'
        if ('quantity' in fieldValues)
            errors.quantity = values.quantity ? '' : 'This field is required'
        if ('price' in fieldValues)
            errors.price = values.price ? '' : 'This field is required'
        if ('category' in fieldValues)
            errors.category = values.category.length != 0 ? '' : 'This field is required'
        setErrors({
            ...errors
        })
        if (fieldValues == values)
            return Object.values(errors).every((formValues) => formValues == '')
    }
    const { values, setValues, handleChange, errors, setErrors, resetForm } = useForm(initialValues, true, validate)

    const handleSubmit = (e) => {
        console.log('handleSubmit',props)
        e.preventDefault()
        if (validate())
        {
            props.onSubmit(values)
        }
    }
    return (
        <Form onSubmit={handleSubmit}>
            <Grid container>
                <Grid item>
                    <Input
                        name='name'
                        value={values.name}
                        label='Name'
                        onChange={handleChange}
                        error={errors.name} />
                    <Input
                        label='Description'
                        name='description'
                        value={values.description}
                        onChange={handleChange}
                        error={errors.description} />
                    <Input
                        label='Quantity'
                        name='quantity'
                        value={values.quantity}
                        onChange={handleChange}
                        error={errors.quantity} />
                    <Input
                        label='Price'
                        name='price'
                        value={values.price}
                        onChange={handleChange}
                        error={errors.price} />
                    <DatePicker
                        name='dop'
                        label='Date Of Purchase'
                        value={values.dop}
                        onChange={handleChange} />
                    <Select
                        name='category'
                        label='Category'
                        value={values.category}
                        onChange={handleChange}
                        options={productService.getProductCollection()}
                        error={errors.category} />
                    <div>
                        <Button variant='contained'
                            color='primary'
                            size='large'
                            text='Submit'
                            type='submit' />
                    </div>
                </Grid>
            </Grid>
        </Form>
    )
}

export default FormProduct
 

AddProduct.js

 import React from 'react'
import {connect} from 'react-redux'
import {addProduct} from 'redux'
import FormProduct from './FormProduct'

const AddProduct = (props) => {
    const onSubmit=(product)=>{
        props.addProduct(product)
    }
    return (
        <div>
            <FormProduct onSubmit={onSubmit}/>
        </div>
    )
}

export default connect(null,{addProduct:addProduct})(AddProduct)
 

actions.js

 import products from '../apis/products'
import {ADD_PRODUCT,LIST_ALL_PRODUCTS} from './types'
import { v4 as uuid } from 'uuid'

export const addProduct=(productDetails)=>{
    return async (dispatch)=>{
        const productId=uuid()
        const response=await products.post('/products',{...productDetails,productId})
        dispatch({
            type:ADD_PRODUCT,
            payload:response.data
        })
    }
}
 

reducers.js

 import {ADD_PRODUCT} from '../actions/types'
import _ from 'lodash'

const productsReducer=(state={},action)=>{
    switch(action.type){
        case ADD_PRODUCT:
            return {...state,[action.payload.id]:action.payload}
        default:
            return state
    }
}

export default productsReducer
 

Комментарии:

1. Я думаю, что в данном случае вы импортируете свое действие не из, redux а из файла, который вы его определили actions.js . Вы можете попробовать это?

2. Я импортировал добавить продукт из файла actions, но я все еще получаю ту же ошибку

3. В чем props.onSubmit проблема? Тот, который передается AddProduct из connect HOC, тот, который передается FormProduct , или тот, который передается form элементу?

4. @DrewReese HOC передается addProduct , а не onSubmit , и HOC prop также вызывается правильно как props.addProduct , так что определенно не HOC из кода, который мы здесь показываем.

5. @phry О, верно, слишком углубился при поиске использования «onSubmit».

Ответ №1:

Это не ошибка redux, поскольку onSubmit это обычный react prop, который вы передаете вручную. Там может быть что-то не так, но из этих фрагментов не очевидно, что именно. Но ничего, связанного с сокращением.

Однако несколько слов о вашем использовании redux: если вы изучаете redux прямо сейчас, вы следуете устаревшему источнику. Redux значительно изменился за последние два года. Если вы будете следовать официальным рекомендациям, modern redux не будет содержать

  • использование connect для компонентов функций (вместо этого используйте useDispatch и useSelector )
  • типы строковых действий, написанных вручную
  • написанные от руки действия или создатели действий
  • использование switch …case или неизменяемой логики в редукторах

Пожалуйста, удалите любой учебник, который вы просматриваете, и вместо этого следуйте официальным руководствам redux. Вероятно, вы будете писать только 1/3 кода, который вы пишете прямо сейчас.

Комментарии:

1. Если вы имеете в виду redux-toolkit, то я согласен, это, безусловно, менее шаблонно. Я не согласен с рекомендацией отказаться от connect HOC, поскольку это позволяет вам писать независимые от redux / state-management презентационные компоненты пользовательского интерфейса.

2. @DrewReese Я цитирую официальное руководство по стилю по этому поводу: redux.js.org/style-guide/style-guide / … Если вы хотите написать чисто презентационные компоненты, вы все равно можете сделать это с помощью хуков — разделив компоненты на «хуки» и «тупые» компоненты. Немного больше кода, но все же его намного легче освоить людям, привыкшим к современному React, чем работать с HOC. Большинство людей просто больше не делают этого различия, хотя в любом случае (большинство компонентов в конечном итоге получат useState amp; useEffect), поэтому применять его по умолчанию действительно не очень хорошая идея.