首页 > 解决方案 > 组件安装后未选择频道列表中的第一项

问题描述

我想要实现的是,在从 firebase 实时数据库中获取频道后,我想自动从频道列表中选择第一项。

问题描述:组件挂载后,我想从 firebase 实时数据库中获取所有通道数据。然后我想选择第一项作为当前频道。看起来更新内部状态on("child_added", cb)无法正常工作。

这是我的 Channels 组件的完整代码:

import React, { useState, useEffect } from "react";
import { Icon, Menu, Modal, Form, Input, Button } from "semantic-ui-react";
import { useForm } from "react-hook-form";
import { useDispatch, useSelector } from "react-redux";
import firebase from "../../firebase";
import { setCurrentChannel } from "../../redux/channelSlice";

export default function Channels({ currentUser }) {
  const [channels, setChannels] = useState([]);

  const [loading, setLoading] = useState(false);

  const [showModal, setShowModal] = useState(false);

  const channelsRef = firebase.database().ref("channels");

  const { currentChannel } = useSelector((state) => state.channel);

  const dispatch = useDispatch();

  const { register, handleSubmit, setValue, trigger } = useForm();

  const openModal = () => setShowModal(true);
  const closeModal = () => setShowModal(false);

  // form submit handler
  const onSubmit = async (data) => {
    setLoading(true);

    const key = channelsRef.push().key;

    const newChannel = {
      id: key,
      name: data.channelName,
      details: data.channelDetails,
      createdby: {
        name: currentUser.displayName,
        avatar: currentUser.photoURL,
      },
    };

    try {
      await channelsRef.child(key).update(newChannel);
      closeModal();
      setLoading(false);
    } catch (error) {
      setLoading(false);
      console.log(error);
    }
  };

  // Input Change Handler
  const onInputChange = async (e, { name, value }) => {
    setValue(name, value);
    await trigger(name);
  };

  // Channnel list listener
  const addListeners = () => {
    channelsRef.on("child_added", (snap) => {
      setChannels((currentChannels) => [...currentChannels, snap.val()]);
    });
  };

  // Channel change Handler
  const changeChannel = (channel) => {
    dispatch(setCurrentChannel(channel));
  };

  useEffect(() => {
    register({ name: "channelName" }, { required: true });
    register({ name: "channelDetails" }, { required: true });
  }, [register]);

  useEffect(() => {
    addListeners();
    if (channels?.length) {
      dispatch(setCurrentChannel(channels[0]));
    }
    // eslint-disable-next-line
  }, []);

  return (
    <>
      <Menu.Menu style={{ paddingBottom: "2em" }}>
        <Menu.Item>
          <span>
            <Icon name="exchange" /> CHANNELS
          </span>{" "}
          ({channels?.length})
          <Icon name="add" onClick={openModal} style={{ cursor: "pointer" }} />
        </Menu.Item>
        {/* Channels */}
        {channels?.map((channel) => (
          <Menu.Item
            key={channel.id}
            onClick={() => changeChannel(channel)}
            name={channel.name}
            style={{ opacity: 0.7 }}
            active={channel.id === currentChannel?.id}
          >
            # {channel.name}
          </Menu.Item>
        ))}
      </Menu.Menu>

      {/* Add Channel Modal */}
      <Modal
        basic
        open={showModal}
        onClose={closeModal}
        closeOnDimmerClick={false}
      >
        <Modal.Header>Add a Channel</Modal.Header>

        <Modal.Content>
          <Form id="channel-add-form" onSubmit={handleSubmit(onSubmit)}>
            <Form.Field>
              <Input
                fluid
                label="Name of channel"
                name="channelName"
                onChange={onInputChange}
              />
            </Form.Field>
            <Form.Field>
              <Input
                ref={register}
                fluid
                label="About the channel"
                name="channelDetails"
                onChange={onInputChange}
              />
            </Form.Field>
          </Form>
        </Modal.Content>
        <Modal.Actions>
          <Button
            form="channel-add-form"
            type="submit"
            color="green"
            loading={loading}
          >
            <Icon name="checkmark" /> Add
          </Button>
          <Button color="red" onClick={closeModal}>
            <Icon name="cancel" /> Cancel
          </Button>
        </Modal.Actions>
      </Modal>
    </>
  );
}

标签: reactjsreact-hooks

解决方案


推荐阅读