@Fierfoxik

Как правильно передать action в reducer из компонента?

Сколько бы не перечитывал документацию так и не могу понять как диспатчнуть правильно actions с данными или как правильно принять их в Reducer.

Как я понимаю мне только нужно как то передать в редюсер actions в который будут падать мои данные

И еще для примера мне подкинули код с this и ref атрибутом в компоненте , я так и не понял для чего это нужно и почему в this падает null.

Честно говоря уже в край запутался и начинают опускаться руки от того что не получается сделать простую вещь, если кто то может досконально объяснить буду очень признателен.

action
export const addItem = (book) => { return { type: 'BUTTON_CLICK',book} }


reducer
export default function rootReducer(state = [], action) {
    console.log(action);
    if(action.type === 'BUTTON_CLICK'){
        return[
        ...state,
            action.book
        ]
            store.dispatch(state)
    }
    return state;
}


Component
import React, { Component } from 'react';
import { dispatch } from 'redux'
import addItem from '../actions/userActions'
import rootReducer from '../reducers/reducers'

export default class Inputs extends Component {
    render() {
function takeVal() {
    console.log(this)
    const name = this.inputName.value;
    const author = this.inputAuthor.value;

    rootReducer.dispatch(addItem(author, name));

    // для очистки инпутов
    this.inputName.value = '';
    this.inputAuthor.value = '';
}
        return (
            <div className="app__enter">
                <div className="inputs-bock">
                    <input className="inputs-book__author" placeholder="Автор" ref={ (input) => this.inputAuthor = input } type="text"/>
                    <input className="inputs-book__name" placeholder="Название" ref={ (input) => this.inputName = input } type="text"/>
                </div>
                <div className="button-wrap">
                    <button onClick={takeVal}>Добавить книгу</button>
                </div>
            </div>
        )
    }
}
  • Вопрос задан
  • 3179 просмотров
Решения вопроса 1
maxfarseer
@maxfarseer
https://maxpfrontend.ru, обучаю реакту и компании
export default function rootReducer(state = [], action) {
    console.log(action);
    if(action.type === 'BUTTON_CLICK'){
        return[
        ...state,
            action.book
        ]
            store.dispatch(state) // выкинуть отсюда.
    }
    return state;
}


В компоненте, используйте state, в нем храните name и author. По клику на кнопку, вам нужно вызвать ACTION. Скорее всего он вам придет из родителя-контейнера (компонента, который присоединен к store, с помощью функции connect).

Inputs переписать можно так:
export default class Inputs extends Component {
    constructor(props) {
        super(props)
        this.onAuthorChange = this.onAuthorChange.bind(this)
        this.onNameChange = this.onNameChange.bind(this)
        this.takeVal = this.this.takeVal.bind(this)
        this.state = {
            author: '',
            name: '',
        }
    }
    onAuthorChange(e) {
        this.setState({ author: e.target.value })
    }
    onNameChange(e) {
        this.setState({ name: e.target.value })
    }
    takeVal() {
        this.props.addItem({ // имя, под которым вы передали свой экшен в качестве пропса от родителя
            author: this.state.author,
            name: this.state.name,
        })
    }
    render() {
        const {author, name} = this.state
        return (
            <div className="app__enter">
                <div className="inputs-bock">
                    <input onChange={this.onAuthorChange} className="inputs-book__author" placeholder="Автор" type="text" value={author}/>
                    <input onChange={this.onNameChange} className="inputs-book__name" placeholder="Название" type="text" value={name}/>
                </div>
                <div className="button-wrap">
                    <button onClick={this.takeVal}>Добавить книгу</button>
                </div>
            </div>
        )
    }
}


Конечно, так как код функций onAuthorChange и onNameChange одинаковый, его можно уместить (и очень просто) в одной функции...

Ваш "приконекченый родитель" может выглядеть так:

import React, { Component } from 'react'
import Inputs from '../components/Inputs'
import { connect } from 'react-redux'

import {
  addItem,
} from '../../actions/UserActions'

class InputsContainer extends Component {
  render() {
    return <Inputs addItem={this.props.addItem} />
  }
}

const mapStateToProps = (state) => ({})

const mapDispatchToProps = (dispatch) => ({
  addItem: (params) => dispatch(addItem(params)),
})

export default connect(mapStateToProps, mapDispatchToProps)(InputsContainer)


p.s. доки читать нужно, поддерживаю. ДЗ: переименовать addItem в пропсах и вызвать его внутри takeVal. Сделать из 2х функций обработчиков изменений в инпутах - одну.
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
@vshvydky
Сразу видно, доки ты не читаешь, а потому совет простой, прочесть от корки до корки доку по редаксу, естьрусский перевод .
Ответ написан
Комментировать
RomReed
@RomReed
JavaScript, Flutter, ReactNative, Redux, Firebase
Документация: https://rajdee.gitbooks.io/redux-in-russian/conten...
Там есть простые примеры. Скачай посмотри и поиграйся пока не наймёшь как всё работает.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы