Хранилище Redux не обновляется

#reactjs #react-redux

#reactjs #react-redux

Вопрос:

Мне нужно отобразить вложенный массив. Но я не могу отобразить вложенный список, поскольку мое хранилище redux не обновляется. Ниже приведен пример структуры данных:

 {
email: "fgh@gmail.com"
tId: 2
teacherClasses: null
teacherUserRef: 3
user:
{
admin: null
firstName: "fgh"
id: 3
lastName: "fgh"

}}
  

Я не могу отобразить ничего, что находится внутри пользователя.

ниже приведен код:

Редуктор:

 import { ACTION_TYPES } from "../actions/teacher";
const initialState = {
    list: []
   
}


export const teacher = (state = initialState, action) => {

    switch (action.type) {
        case ACTION_TYPES.FETCH_ALL:
            
            return {
                ...state,
                list: [
                    ...action.payload]
            }
        case ACTION_TYPES.FETCHBYID:
            return {
                ...state,
                list: [action.payload]
            }

        case ACTION_TYPES.CREATE:
            return {
                ...state,
                list: [...state.list, action.payload]
            }

        case ACTION_TYPES.UPDATE:
            return {
                ...state,
                list: state.list.map(x => x.id == action.payload.id ? action.payload : x)
            }

        case ACTION_TYPES.DELETE:
            return {
                ...state,
                list: state.list.filter(x => x.id != action.payload)
            }

        default:
            return state
    }
}
  

Страница компонента:

Teacher.js:

 
const Teacher = ({ ...props }) => {
    const [currentId, setCurrentId] = useState(0)

    useEffect(() => {
        console.log("teacher call")
        
        props.fetchAllTeacher()
        console.log(props.teacherList)
    }, [currentId])//componentDidMount

    return (
        <div className="site-layout-background" style={{ padding: 24, textAlign: 'center' }}>
        <Space direction="vertical" align="center">
                
                        <TableContainer>
                            <Table>
                                <TableHead >
                                    <TableRow>
                                        <TableCell>Name</TableCell>
                                        <TableCell>Email</TableCell>

                                        <TableCell></TableCell>
                                    </TableRow>

                                    {
                                        
                                         props.teacherList.map((record, index) => {
                                        return (<TableRow key={index} hover>
                                            <TableCell>{record.email}</TableCell>
                                            <TableCell>{record.user.firstName}</TableCell>
                                            <TableCell>
                                                <ButtonGroup variant="text">
                                                    <Button icon={<DeleteOutlined />} onClick={() => onDelete(record.user.id)}></Button>
                                                </ButtonGroup>
                                            </TableCell>
                                            

                                        </TableRow>)
                                    })}
                                </TableHead>
                                <TableBody>
                                    
                                </TableBody>
                            </Table>
                        </TableContainer>

            </Space>
            </div>
            
        
    );
}

const mapStateToProps = state => ({
    teacherList: state.teacher.list,
    userList: state.user.list
})

const mapActionToProps = {
    fetchAllTeacher: actions.fetchAll,
    deleteUser: actions1.Delete
}

export default connect(mapStateToProps, mapActionToProps)(Teacher);
  

Создатель действия:

 import api from "./api";

export const ACTION_TYPES = {
    CREATE: 'CREATE',
    UPDATE: 'UPDATE',
    DELETE: 'DELETE',
    FETCH_ALL: 'FETCH_ALL',
    FETCHBYID: 'FETCHBYID'
}



export const fetchAll = () => dispatch => {
    api.teacher().fetchAll()
        .then(response => {
            dispatch({
                type: ACTION_TYPES.FETCH_ALL,
                payload: response.data
            })
        })
        .catch(err => console.log(err))
}
export const fetchById = (id) => dispatch => {
    api.teacher().fetchById(id)
        .then(response => {
            dispatch({
                type: ACTION_TYPES.FETCHBYID,
                payload: response.data
            })
        })
        .catch(err => console.log(err))
}

export const create = (data, onSuccess) => dispatch => {

    api.teacher().create(data)
        .then(res => {
            dispatch({
                type: ACTION_TYPES.CREATE,
                payload: res.data
            })
            onSuccess()
        })
        .catch(err => console.log(err))
}

export const update = (id, data, onSuccess) => dispatch => {

    api.teacher().update(id, data)
        .then(res => {
            dispatch({
                type: ACTION_TYPES.UPDATE,
                payload: { id, ...data }
            })
            onSuccess()
        })
        .catch(err => console.log(err))
}

export const Delete = (id, onSuccess) => dispatch => {
    api.teacher().delete(id)
        .then(res => {
            dispatch({
                type: ACTION_TYPES.DELETE,
                payload: id
            })
            onSuccess()
        })
        .catch(err => console.log(err))
}
  

Я получаю сообщение об ошибке, в котором указано, что FirstName не определено.

Пожалуйста, помогите.

Ответ №1:

  • Рекомендация

Поскольку вы используете функциональный компонент, вам следует использовать react-redux такие перехваты, как useSelector , useDispatch .

 import { useSelector, useDispatch } from "react-redux"

...
teacherList = useSelect(state => state.teacher.list)
userList = useSelect(state => state.user.list)

const dispatch = useDispatch()
...
{
dispatch(actions.fetchAll(...))
dispatch(actions1.Delete(...))
}

  
  • Проблема

Во-первых, вам не нужно устанавливать currentId как зависимость useEffect .

Когда зависимость представляет собой пустой список, обратный вызов будет выполняться только один раз, аналогично componentDidMount .

Во-вторых, fetchAllTeacher это асинхронное действие, которое означает, что вам нужно подождать, пока все учителя не будут успешно извлечены.

Итак, вам нужно добавить функцию отложенной загрузки.

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

1. Большое спасибо. Я буду использовать useSelector, useDispatch.. Но это вызывает проблемы?

2. Я рекомендую использовать его. Это не обязательно. Кстати, пожалуйста, поделитесь console.log(props.teacherList) результатом.

3. спасибо за ваше время. ниже приведен результат: 0: email: "pashmina@gmail.com" tId: 1 teacherClasses: null teacherUserRef: 2 user: admin: null firstName: "pashmina" id: 2 __proto__: Object __proto__: Object 1: email: "vijeth@gmail.com" tId: 2006 teacherClasses: null teacherUserRef: 1013 user: admin: null firstName: "vjv" id: 1013 __proto__: Object __proto__: Object 2: email: "shyamal.bhat@gmail.com" tId: 2007 teacherClasses: null teacherUserRef: 1014 user: admin: null firstName: "lamini" id: 1014

4. результат всегда задерживается

5. Попробуйте {record.user? .FirstName}

Ответ №2:

Причина, по которой ваше хранилище redux не обновляется, заключается в том, что вы должны отправить действия. Правильная подпись для mapDispatchToProps :

 const mapDispatchToProps = (dispatch) => {
    fetchAllTeacher: () => dispatch(actions.fetchAll()),
    deleteUser: (id) => dispatch(actions.Delete(id)),
}

export default connect(mapStateToProps, mapDispatchToProps)(Teacher);
  

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

Это может работать следующим образом:

 import { useSelector, useDispatch } from "react-redux"

const Teacher = ({ ...props }) => {
    const dispatch = useDispatch();
    useEffect(() => {
        console.log("teacher call")
        
        const teachers = props.fetchAllTeacher();
        // dispatch the action that will add the list to the redux state
        dispatch(actions.fetchAll(teachers));
    }, [currentId]);
    
    // fetch the teacher list from redux store

    const teacherList = useSelector(state => state.teacher.list);
    return (...);
}
  

Рассмотрите возможность перемещения определения селектора state => state.teacher.list в его собственный модуль, чтобы вы могли повторно использовать его в других компонентах и обновлять его в одном месте, если структура вашего хранилища изменится.

Похоже, что в вашем коде не было отправлено никаких действий, поэтому проблема не была связана с вложенностью данных. У вас могут быть вложенные данные в вашем состоянии без проблем.

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

1. Большое спасибо. Я удостоверюсь, что не будет смешиваться. Я тоже отправляю действия. Я отредактировал свой вопрос. Пожалуйста, проверьте