Как передать действие Redux в 2 редуктора для обновления состояния в React? - PullRequest
0 голосов
/ 14 апреля 2020

В моем приложении есть компонент, активируемый нажатием кнопки CurrentStatus, который передает service.id родительскому компоненту Dashboard и получает service_notes через действие Redux с axios.get. service_notes передаются в редуктор и в хранилище Redux. Затем я connect в хранилище в ServiceLogs компоненте и перебираю массив для отображения в render() на DOM. ServiceLogs - это компонент типа комментариев, в который пользователь может добавлять заметки. Я могу создавать заметки, но не могу обновить состояние. Моим последним подходом было выполнение действия CREATE_NOTE и использование его в notesReducer AND serviceNotesReducer. Это все еще не обновляет состояние и DOM.

Вот мой макет:

Dashboard_wirefram

Вот соответствующие компоненты:

Панель инструментов:

import React, { Component } from "react";
import { connect } from "react-redux";
import { Container, Grid, Button } from "semantic-ui-react";
import CurrentStatus from "./components/CurrentStatusComponent";
import KnownOutages from "./components/KnownOutagesComponent";
import ServiceLogs from "./components/ServiceLogsComponent";
import { getServices } from "./actions/getServicesAction";
import { getServiceNotes } from "./actions/getServiceNotesAction";
import { getOutages } from "./actions/getOutagesAction";


class Dashboard extends Component {
    state = {
        serviceNotes: null,
        serviceOutages: null,
        showServiceLogs: "none",
    }

  componentDidMount() {
    this.props.getServices();
    this.props.getOutages();
  }

  displayServiceLogs = serviceId => {
    debugger 
    this.props.getServiceNotes(serviceId)
     this.setState({ showServiceLogs: "none" ? "block" : "none"}); 
  }

  render() {
      console.log(this.state)
    return (
      <>
        <Container fluid>
          <h1>TML Dashboard</h1>
        </Container>

        <Grid columns={3} divided>
          <Grid.Row>
            <Grid.Column width={5}>Service Log</Grid.Column>
            <Grid.Column width={6}>Current Status</Grid.Column>
            <Grid.Column width={3}>Known Outages</Grid.Column>
          </Grid.Row>
          <Grid.Row>
            <Grid.Column width={5}>
              <ServiceLogs showServiceLogs={this.state.showServiceLogs}/>
            </Grid.Column>
            <Grid.Column width={6}>
              <CurrentStatus displayServiceLogs={this.displayServiceLogs}/>
            </Grid.Column>
            <Grid.Column width={3}>
              <KnownOutages />
            </Grid.Column>
          </Grid.Row>
        </Grid>
      </>
    );
  }
}

const mapStateToProps = state => {
    return { 
        services: state.services.services,
        notes: state.notes.notes  
    }
}

const mapDispatchToProps = dispatch => {
    return {
    getServices: () => dispatch(getServices()),
    getNotes: () => dispatch(getNotes()),
    getOutages: () => dispatch(getOutages()),
    getServiceNotes: serviceId => dispatch(getServiceNotes(serviceId))
    }
}

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

Вот компонент CurrentStatus, в котором я щелкаю элемент (услугу) и передаю идентификатор на панель инструментов в get из функции getServiceNotes(serviceId) в getServiceNotesActoin:

import React, { Component } from "react";
import { connect } from "react-redux";
import { Table, Header } from "semantic-ui-react";
const uuidv4 = require("uuid/v4")

class CurrentStatus extends Component {

  handleClick = serviceId => {
    this.props.displayServiceLogs(serviceId)
  }

    render() {
        console.log(Object.keys(this.props.services))
        return (
          <>
            <Table celled padded>
              <Table.Header>
                <Table.Row>
                  <Table.HeaderCell singleLine>Service</Table.HeaderCell>
                  <Table.HeaderCell>Status</Table.HeaderCell>
                  <Table.HeaderCell>Reason</Table.HeaderCell>
                </Table.Row>
              </Table.Header>
              <Table.Body>
                {Object.assign(this.props.services).map((service) => (
                  <Table.Row key={uuidv4()}>
                    <Table.Cell
                      onClick={() => this.handleClick(service.id)}
                    >
                      <Header as="h3" textAlign="center">
                        {service.name}
                      </Header>
                    </Table.Cell>
                    <Table.Cell textAlign="center">
                      {service.is_down ? (
                        <h4 style={{ color: "red" }}>Down</h4>
                      ) : (
                        <h4 style={{ color: "green" }}>Up</h4>
                      )}
                    </Table.Cell>
                    <Table.Cell></Table.Cell>
                  </Table.Row>
                ))}
              </Table.Body>
            </Table>
          </>
        );
    }
};

const mapStateToProps = state => {
    return { 
      services: state.services.services 
    }
};


export default connect(mapStateToProps, null)(CurrentStatus);

, а вот компонент ServiceLogs, где я могу отображать и отображать связанные serviceNotes:

import React, { Component } from "react";
import { connect } from "react-redux";
import { Comment, Container, Grid, Form, Button } from "semantic-ui-react";
import { createNote } from "../actions/createNoteAction";
class ServiceLogsComponent extends Component {
    state = {
        entry: ""
    }


    handleChange = (e, { name, value }) => this.setState({ [name]: value })

    handleSubmit = e => {
        e.preventDefault()
        const userId = 2
        const serviceId = this.props.serviceNotes[0].service.id 
        this.props.createNote(this.state.entry, serviceId, userId)
    }

    render() {
    console.log(this.props)
    return (
      <>
        <div style={{ display: this.props.showServiceLogs }}>
          <Comment>
            <Comment.Group>
              {this.props.serviceNotes.map((serviceNote) => (
                <Comment.Content>
                  <Comment.Author as="a">{serviceNote.created_at}</Comment.Author>
                  <Comment.Metadata>{serviceNote.user.username}</Comment.Metadata>
                  <Comment.Text>{serviceNote.entry}</Comment.Text>
                </Comment.Content>
              ))}
              <Form onSubmit={(e) => this.handleSubmit(e)}>
                <Form.TextArea
                  style={{ height: "50px" }}
                  onChange={this.handleChange}
                  name="entry"
                />
                <Form.Button
                  type="submit"
                  content="Add Note"
                  labelPosition="left"
                  icon="edit"
                  primary
                />
              </Form>
            </Comment.Group>
          </Comment>
        </div>
      </>
    );
  }
}

const mapStateToProps = state => {
  return {
    services: state.services.services,
    notes: state.notes.notes,
    serviceNotes: state.serviceNotes.serviceNotes
  };
};

const mapDispatchToProps = dispatch => {
    return {
       createNote: (entry, serviceId, userId) => dispatch(createNote(entry, serviceId, userId)) 

    }
};

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

Поэтому я не могу обновить DOM при создании новой заметки. Я пробовал это в этих 2 редукторах:

const initialState = {
  notes: [],
};

export const notesReducer = (state = initialState, action) => {
  switch (action.type) {
    case "GET_NOTES":
      return { ...state, notes: action.payload };
    case "CREATE_NOTE":
      return {
        ...state,
        notes: [...state.notes, action.payload],
      };
    default:
      return state;
  }
};

и

const initialState = {
  serviceNotes: [],
};

export const serviceNotesReducer = (state = initialState, action) => {
  switch (action.type) {
    case "GET_SERVICE_NOTES":
      return { ...state, serviceNotes: action.payload };
    case "CREATE_SERVICE":
        return { ...state, serviceNotes: [ ...state.serviceNotes, action.payload] }
    default:
      return state;
  }
};

Надеюсь, это достаточно ясно Вкратце: мне нужно ServiceLogs состояние, чтобы изменить действие CRUD.

1 Ответ

0 голосов
/ 14 апреля 2020

Может быть, вам следует следовать рекомендациям Руководства по стилю Redux: https://redux.js.org/style-guide/style-guide Я думаю, что идея состоит в том, чтобы сохранить только один магазин для всего приложения, и вам следует обернуть соединение с магазином в более высоком Уровень (компонентно говоря) с использованием компонента.

enter image description here

Я бы также порекомендовал вам использовать новые Redux Hooks, такие как useSelector, и преобразовывать компоненты вашего класса в React Hooks, чтобы упростить ваш код. , https://reactjs.org/docs/hooks-intro.html

...