首页 > 解决方案 > 围绕 Pusher 重构类组件

问题描述

我通常对此没问题。也许我的大脑有点炸了,我需要离开屏幕一会儿..

为了我的理智,有人可以帮我将以下内容重构为功能组件。

我正在努力移动代码以获取 componenetwillmount 并且理想情况下希望将 axios 替换为 fetch 和 useeffect (所以它类似于我的其余代码)

import React, { Component } from 'react';
import Pusher from 'pusher-js';
import axios from 'axios';
import Grid from '@material-ui/core/Grid';
import CustomGridItem from '../components/Grid/CustomGridItem'
import CardHeader from '@material-ui/core/CardHeader';
import CardContent from '@material-ui/core/CardContent';
import moment from 'moment';

    class App extends Component {
      state = {
        username: '',
        date: '',
        color: "#ffff80",
        newComment: '',
        comments: [],
      };

      updateInput = event => {
        const { name, value } = event.target;
        this.setState({
          [name]: value,
        });
      };

      postComment = event => {
        event.preventDefault();
        const { username, newComment, color } = this.state;
        if (username.trim() === '' || newComment.trim() === '') return;

        const data = {
          name: username,
          text: newComment,
          color: color,
          date: moment().format('MMMM Do YYYY h:mm:ss a'),
        };

        axios
          .post('http://localhost:1234/comment', data)
          .then(() => {
            this.setState({
              username: '',
              newComment: '',
              color: '',
              date: moment().format('MMMM Do YYYY h:mm:ss a')
            });
          })
          .catch(error => console.log(error));
      };

      componentDidMount() {
        const pusher = new Pusher('xxxxxxxxxx', {
          cluster: 'eu',
          encrypted: true,
        });

        axios.get('http://localhost:1234').then(({ data }) => {
          this.setState({
            comments: [...data],
          });
        }).catch(error => console.log(error))

        const channel = pusher.subscribe('comments');
        channel.bind('new-comment', data => {
          this.setState(prevState => {
            const { comments } = prevState;
            comments.push(data.comment);

            return {
              comments,
            };
          });
        });
      }

      render() {
        const { username, newComment, date, color, comments } = this.state;
        const { classes } = this.props;
        const userComments = comments.map(e => (
          <CustomGridItem color={e.color} xs={12} md={12} lg={12} xl={12} key={e._id}>
            <CardHeader title={e.name} subheader={e.date} />
            <CardContent>{e.text}</CardContent>
          </CustomGridItem>
        ));

        return (
          <div className="App">
            <Grid container direction="row" justify="flex-start" alignItems="stretch" spacing={3} >
            {userComments}
            </Grid>
            <br /> <br />
            <section className="comments-form">
              <form onSubmit={this.postComment}>
                <label htmlFor="username">Name:</label><br />
                <input
                  className="username"
                  name="username"
                  id="username"
                  type="name"
                  value={username}
                  onChange={this.updateInput}
                />
                <input
                  className="date"
                  name="date"
                  id="date"
                  type="hidden"
                  value={date}
                />
                <br />
                <label htmlFor="new-comment">Comment:</label><br />
                <textarea
                  name="newComment"
                  id="new-comment"
                  value={newComment}
                  onChange={this.updateInput}
                /><br />
                <label htmlFor="new-comment">Note colour:</label><br />
                <input
                  type="color"
                  name="color"
                  id="color"
                  value={color}
                  onChange={this.updateInput}></input><br /><br />
                <button type="submit">Add Note!</button>
              </form>
            </section>
          </div>
        );
      }
    }

    export default App;

我应该补充一下,以下是我尝试过的......我现在设法将帖子拉过,但只要我点击一个表单元素,我就会得到一个“无法读取未定义的 map.e 的属性(第 84 行) - 在下面的评论帮助后更新:)

import React, { useState, useEffect } from 'react';
import Pusher from 'pusher-js';
import axios from 'axios';
import Grid from '@material-ui/core/Grid';
import CustomGridItem from '../components/Grid/CustomGridItem'
import CardHeader from '@material-ui/core/CardHeader';
import CardContent from '@material-ui/core/CardContent';
import moment from 'moment';

const App = (props) => {
  const [formData, setFormData] = useState({
                                    username: '',
                                    date: '',
                                    color: '#ffff80',
                                    newComment: ''})

  const [comments, setComments] = useState([])

  const updateInput = event => {
        const { name, value } = event.target;
        setFormData({
          [name]: value,
        });
        console.log(username)
        console.log(newComment)
      };

  const postComment = event => {
        event.preventDefault();
        const { username, newComment, color } = formData;
        if (username.trim() === '' || newComment.trim() === '') return;

        const data = {
          name: username,
          text: newComment,
          color: color,
          date: moment().format('MMMM Do YYYY h:mm:ss a'),
        };

        axios
          .post('http://localhost:1234/comment', data)
          .then(() => {
            setFormData({
              username: '',
              newComment: '',
              color: '',
              date: moment().format('MMMM Do YYYY h:mm:ss a')
            });
          })
          .catch(error => console.log(error));
      };

      useEffect(() => {

        const fetchData = async () => {

        const pusher = new Pusher('xxxxxxxxxx', {
          cluster: 'eu',
          encrypted: true,
        });

        axios.get('http://localhost:1234').then(({ data }) => {
          setComments([...data]);
        }).catch(error => console.log(error))

        const channel = pusher.subscribe('comments');
        channel.bind('new-comment', data => {
          setComments(prevState => {
            const { comments } = prevState;
            comments.push(data.comment);

            return {
              comments,
            };
          });
        });

      }

      fetchData();

    }, []);



        const { username, newComment, date, color } = formData;
        const { classes } = props;
        const userComments = comments.map(e => (
          <CustomGridItem color={e.color} xs={10} md={10} lg={10} xl={10} key={e._id}>
            <CardHeader title={e.name} subheader={e.date} />
            <CardContent>{e.text}</CardContent>
          </CustomGridItem>
        ));

        return (
          <div className="App">
            <Grid container direction="row" justify="center" alignItems="stretch" spacing={3} >
            {userComments}
            </Grid>
            <br /> <br />
            <section className="comments-form">
              <form onSubmit={postComment}>
                <label htmlFor="username">Name:</label><br />
                <input
                  className="username"
                  name="username"
                  id="username"
                  type="name"
                  value={username}
                  onChange={updateInput}
                />
                <input
                  className="date"
                  name="date"
                  id="date"
                  type="hidden"
                  value={date}
                />
                <br />
                <label htmlFor="new-comment">Comment:</label><br />
                <textarea
                  name="newComment"
                  id="new-comment"
                  value={newComment}
                  onChange={updateInput}
                /><br />
                <label htmlFor="new-comment">Note colour:</label><br />
                <input
                  type="color"
                  name="color"
                  id="color"
                  value={color}
                  onChange={updateInput}></input><br /><br />
                <button type="submit">Add Note!</button>
              </form>
            </section>
          </div>
        );

    }

    export default App;

标签: reactjspusher

解决方案


你的axios.post(...).then(...)电话setState没有comments。setter foruseState不会像在类组件中那样合并对象,而是完全替换值。

所以点击按钮后 - >运行postComment你结束了

.then(() => {
  setState({
    username: "",
    newComment: "",
    color: "",
    date: moment().format("MMMM Do YYYY h:mm:ss a")
});

当然,在重新渲染你的commentsis之后undefined

处理该问题的最简单方法是将状态拆分为几个独立变量,例如

const [formData, setFormData] = useState({
  username: '',
  date: '',
  color: "#ffff80",
  newComment: ''
});
const [allComments, setAllComments] = useState([]);

所以他们不会互相干扰。


推荐阅读