Путать с действиями и редукторами REDUX - PullRequest
0 голосов
/ 28 февраля 2019

, поэтому я пытаюсь изменить код из моего предыдущего вопроса:

Реагировать: Как обновить один компонент, когда что-то происходит с другим компонентом

Итак, яначал копаться в существующем шаблоне кода, чтобы посмотреть, как он реализован.

Я нашел файл redurs.js, в который я добавил новый редуктор: ActiveTenant

import Auth from './auth/reducer';
import App from './app/reducer';
import ThemeSwitcher from './themeSwitcher/reducer';
import LanguageSwitcher from './languageSwitcher/reducer';
import ActiveTenant from './activetenant/reducer';

export default {
  Auth,
  App,
  LanguageSwitcher,
  ThemeSwitcher,
  ActiveTenant
};

Этот новый редуктор похож на этот:

import { Map } from 'immutable';
import actions from './actions';
import { adalApiFetch } from '../../adalConfig';

const initState = new Map({
    tenantId: ''
});

export default function(state = initState, action) {
  switch (action.type) {
    case actions.SET_TENANT_ACTIVE:
    {
        const options = { 
            method: 'post'
        };

        adalApiFetch(fetch, "/Tenant/SetTenantActive?TenantName="+state.tenantId, options)
        .then(response =>{
            if(response.status === 200){
                console.log("Tenant activated");
            }else{
                throw "error";
            }
        })
        .catch(error => {
            console.error(error);
        });

        return state.set('tenant', state.Name);
    }
    default:
      return state;
  }
}

и действия для этого редуктора

const actions = {
  SET_TENANT_ACTIVE: 'SET_TENANT_ACTIVE',
  setTenantActive: () => ({
    type: actions.SET_TENANT_ACTIVE
  }),
};
export default actions;

Затем из самого компонента мне нужно вызвать действие, когда строка выбрана во внешнем интерфейсе, поэтому я произвел рефакторингзакомментированный код в одну строку.

import React, { Component } from 'react';
import {  Table, Radio} from 'antd';
import { adalApiFetch } from '../../adalConfig';
import Notification from '../../components/notification';
import actions from '../../redux/activetenant/actions';

const { setTenantActive } = actions;

class ListTenants extends Component {

    constructor(props) {
        super(props);
        this.state = {
            data: []
        };
    }



    fetchData = () => {
        adalApiFetch(fetch, "/Tenant", {})
          .then(response => response.json())
          .then(responseJson => {
            if (!this.isCancelled) {
                const results= responseJson.map(row => ({
                    key: row.id,
                    TestSiteCollectionUrl: row.TestSiteCollectionUrl,
                    TenantName: row.TenantName,
                    Email: row.Email
                  }))
              this.setState({ data: results });
            }
          })
          .catch(error => {
            console.error(error);
          });
      };


    componentDidMount(){
        this.fetchData();
    }

    render() {
        const columns = [
                {
                    title: 'TenantName',
                    dataIndex: 'TenantName',
                    key: 'TenantName',
                }, 
                {
                    title: 'TestSiteCollectionUrl',
                    dataIndex: 'TestSiteCollectionUrl',
                    key: 'TestSiteCollectionUrl',
                }, 
                {
                    title: 'Email',
                    dataIndex: 'Email',
                    key: 'Email',
                }
        ];

        // rowSelection object indicates the need for row selection
        const rowSelection = {
            onChange: (selectedRowKeys, selectedRows) => {
                if(selectedRows[0].TenantName != undefined){
                    console.log(selectedRows[0].TenantName);
                    const options = { 
                        method: 'post'
                    };

                    setTenantActive(selectedRows[0].TenantName);
                    /* adalApiFetch(fetch, "/Tenant/SetTenantActive?TenantName="+selectedRows[0].TenantName.toString(), options)
                        .then(response =>{
                        if(response.status === 200){
                            Notification(
                                'success',
                                'Tenant set to active',
                                ''
                                );
                        }else{
                            throw "error";
                        }
                        })
                        .catch(error => {
                        Notification(
                            'error',
                            'Tenant not activated',
                            error
                            );
                        console.error(error);
                    }); */
                }
            },
            getCheckboxProps: record => ({
                type: Radio
            }),
        };

        return (
            <Table rowSelection={rowSelection} columns={columns} dataSource={this.state.data} />
        );
    }
}

export default ListTenants;

Однако мне не ясно, как соотносятся действие и редуктор, если я проверяю отладчик, действие выполняется, и ни один параметр не получен, норедуктор никогда не выполняется.

Должен ли я куда-то отправлять отправку? Что мне не хватает в этой головоломке?

Ответы [ 3 ]

0 голосов
/ 28 февраля 2019

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

Ref.https://redux -starter-kit.js.org / api / createaction

Мы могли бы написать типы действий в виде встроенных строк в обоих местах.Создатели действий хороши, но они не обязаны использовать Redux - компонент может пропустить предоставление аргумента mapDispatch для подключения и просто вызвать this.props.dispatch ({type: "CREATE_POST", payload: {id: 123,title: "Hello World"}}) сам.

Реф.https://redux -starter-kit.js.org / использование / использование-гид

0 голосов
/ 19 мая 2019

Итак, первое, что нужно понять, это Redux Cycle :

Action Creator -> Action -> dispatch -> Reducers -> State

Создатель действия : Создатель действия - это функция, которая собирается создать или вернуть простой объект JavaScript, известный как Действие со свойством type и *Свойство 1014 *, которое описывает некоторые изменения, которые вы хотите внести в свои данные.

Свойство payload описывает некоторый контекст вокруг изменения, которое мы хотим внести.

Цель Действие предназначено для описания некоторых изменений данных в нашем приложении.

Создатель действий предназначен для создания Действие .

.Функция dispatch будет принимать Действие , делать копии этого объекта и передавать его множеству различных мест внутри нашего приложения, что приводит нас к Редукторам .

В Redux редуктор - это функция, отвечающая за принятие Actион .Он собирается обработать это Action , внести некоторые изменения в данные и вернуть их, чтобы их можно было централизовать в каком-то месте.

В Redux свойство State центральное хранилище всей информации, производимой нашими редукторами .Вся информация консолидируется внутри объекта State , поэтому наше приложение React может легко добраться до нашей стороны приложения Redux и получить доступ ко всем данным внутри приложения.

Таким образом, таким образомприложению не нужно обходить каждый отдельный редуктор и запрашивать текущее состояние .

Так что переварите это на пару минут, а затем посмотрите на свою архитектуру.

Давайте перейдем к редукторам .

Редукторы вызываются с помощью Действие , созданного Создатель действий .Редуктор рассмотрит это Действие и решит, нужно ли ему модифицировать некоторые данные на основе этого Действие .

Итак, другими словами, работаРедуктор предназначен не для выполнения запросов API, а для обработки действий, отправленных ему создателем действия.

Поэтому вместо этого:

import { Map } from 'immutable';
import actions from './actions';
import { adalApiFetch } from '../../adalConfig';

const initState = new Map({
    tenantId: ''
});

export default function(state = initState, action) {
  switch (action.type) {
    case actions.SET_TENANT_ACTIVE:
    {
        const options = { 
            method: 'post'
        };

        adalApiFetch(fetch, "/Tenant/SetTenantActive?TenantName="+state.tenantId, options)
        .then(response =>{
            if(response.status === 200){
                console.log("Tenant activated");
            }else{
                throw "error";
            }
        })
        .catch(error => {
            console.error(error);
        });

        return state.set('tenant', state.Name);
    }
    default:
      return state;
  }
}

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

import { SET_TENANT_ACTIVE } from "../actions/types";

const initialState = {
    tenantId: ''
};

export default (state = initialState, action) {
  switch (action.type) {
    case SET_TENANT_ACTIVE:
      return {...state, [action.payload.id]: action.payload };
    default:
      return state;
  }
}

Тогда внутри вашего файла создателей действий у вас должен быть создатель действий, который выглядит примерно так:

import axios from 'axios';
import { SET_TENANT_ACTIVE } from "../actions/types";


export const setTenant = id => async (dispatch) => {
  const response = await axios.post(`/tenants/${id}`);

  dispatch({ type: SET_TENANT_ACTIVE, payload: response.data });
};

Вам также нужно узнать о структуре проекта Redux, потому что после вышеупомянутого рефакторинга выне хватает, как подключить все это к вашему компоненту.В вашем компонентном файле нет функции connect(), для которой также требуется тег Provider, а у вас его нет.

Поэтому для этого я рекомендую прежде всего настроить папку и структуру файла следующим образом.:

  /src
    /actions
    /components
    /reducers
    index.js

Итак, внутри вашего index.js файла он должен выглядеть примерно так:

import React from "react";
import ReactDOM from "react-dom";
import { Provider } from "react-redux";
import { createStore, applyMiddleware, compose } from "redux";
import reduxThunk from "redux-thunk";

import App from "./components/App";
import reducers from "./reducers";

const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(
  reducers,
  composeEnhancers(applyMiddleware(reduxThunk))
);

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.querySelector("#root")

Итак, ваша цель - убедиться, что вы получите этот тег Provider всамый верх вашей иерархии компонентов и убедитесь, что вы передаете ему ссылку на свое хранилище Redux, в которое загружаются все редукторы .

Итак, выше я создал хранилище и передал егонаш набор редукторов, и он вернет вам все ваши приложения State .

Наконец, вы видите выше, я создал экземпляр <Provider> и обернул компонент <App />с ним, а затем вы хотите передать <Provider> компонент является одной опорой под названием store.store - это результат вызова createStore() и вызова reducers.

* <Provider> - это то, что взаимодействует с Redux store от нашего имени.

Обратите внимание, я также подключил Redux-Thunk, о котором упоминал Дж. Хестерс. Насколько я вижу из вашего кода, вы делаете запрос ajax, поэтому я предложил вам асинхронный создатель действий, а это значит, что вынужен Redux-Thunk или какое-нибудь промежуточное ПО, позвольте мне не оскорблять фанатов Redux-Saga, так что у вас есть, по крайней мере, эти два варианта.Вы, кажется, относительно новичок в Redux, просто используйте Redux-Thunk.

Теперь вы можете использовать компонент connect() внутри вашего файла компонентов, чтобы завершить подключение этих создателей действий и редукторов к вашему компоненту или вашей стороне React.приложение.

import React, { Component } from 'react';
import { connect } from "react-redux";
import {  Table, Radio} from 'antd';
import { adalApiFetch } from '../../adalConfig';
import Notification from '../../components/notification';
import actions from '../../redux/activetenant/actions';

После импорта connect создайте его экземпляр ниже:

export default connect()(ListTenants);

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

Затем вам нужно настроить этот connect() компонент React, добавив mapStateToProps, есливам это понадобится, но обязательно укажите actions в качестве второго аргумента connect().Если вы понимаете, что вам не нужно mapStateToProps, просто передайте null в качестве первого аргумента, но вы не можете оставить его пустым.

Надеюсь, все это было полезно и добро пожаловать в удивительный мирReact-Redux.

0 голосов
/ 28 февраля 2019

Вы неправильно используете редукторы.Редукторы должны быть чистыми. У вас есть побочные эффекты, свидетельствующие о том, что вы еще не поняли Redux.

Вместо того, чтобы записывать решение для вас (что в любом случае потребовалось бы навсегда, так какнужно всего лишь объяснить Redux), я предлагаю вам потратить 3 часа и пройтись по документам Redux и следовать учебникам (они великолепны).

После этого вы можете захотетьпосмотрите на Redux Thunk .Но, вам может не потребоваться thunks .

PS: (Небольшая вещь, чтобы поднять, но я не видел, чтобы кто-нибудь использовал Map s в Redux. Есть ли причина, по которой вы делаетечто? Вы можете вместо этого использовать простые объекты.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...