React Apollo: Как получить доступ к элементу Trix-Editor в компоненте Mutation? - PullRequest
0 голосов
/ 15 апреля 2020

Пожалуйста, мне нужна помощь в доступе к элементу <trix-editor> в моем Mutation компоненте. Я использую React hook useRef() для доступа к этому, но получаю null. Из Chrome Dev Tools (изображение ниже) я вижу, что элемент был передан. Я попробовал некоторые решения, приведенные здесь & здесь , но безуспешно. Кажется, проблема в рендеринге компонента Mutation. Я довольно новичок в React, поэтому не уверен, правильно ли я это понимаю. Что я делаю неправильно? Заранее благодарю за помощь .


enter image description here

Мой код:

const EditProfile = () => {
  const trixInput = useRef(null);
  const [state, setState] = useState({
                              firstName: "",
                              lastName: "",
                              bio: "",
                              avatar: "",
                              gender: "",
                              country: ""
                            });

  let userID
  let { username }    = useParams();
  let userFromStore   = JSON.parse(sessionStorage.getItem('_ev')));
  let history         = useHistory();

  useEffect(() => {
    // trixInput.current.addEventListener("trix-change", event => {
       console.log(trixInput.current); // <<<< this prints null to the screen 
    // })
  },[]);

  if (userFromStore !== username) {
    return (
      <div className="alert">
         <span className="closebtn" onClick={() => history.push("/console")}>&times;</span>
          <strong>Wanning!</strong> Not authorized to access this page.
      </div>
    );
  }
  return (
    <Query query={GetAuthUser}>
      {({ loading, error, data }) => {
        if (loading) return "loading...";
        if (error)   return `Error: ${error}`;

        if (data) {
          let {userId, firstName, lastName, avatar, bio, gender, country} = data.authUser.profile;
          userID = parseInt(userId);

          return (
            <Mutation mutation={UpdateUserProfile}>
              {(editProfile, { loading }) => (
                <div  className="card bg-light col-md-8 offset-md-2 shadow p-3 mb-5 rounded">
                  <article className="card-body">
                    <form onSubmit={ e => {
                      e.preventDefault();
                      editProfile({
                        variables: {
                          userId:    userID,
                          firstName: state.firstName,
                          lastName:  state.lastName,
                          bio:       state.bio,
                          avatar:    state.avatar,
                          gender:    state.gender,
                          country:   state.country
                        }
                      }).then(({ data: { editProfile: { success, errors }  } }) => {
                        success ? alert(success) : alert(errors[0]["message"]);
                      });
                    }}
                    >
                    <div className="form-row mb-3">
                      <div className="col">
                        <input
                          type="text"
                          name="firstName"
                          placeholder="First name"
                          className="form-control"
                          defaultValue={firstName}
                          onChange={e => setState({firstName: e.currentTarget.value})}
                        />
                      </div>
                      <div className="col">
                        <input
                          type="text"
                          name="lastName"
                          placeholder="Last name"
                          className="form-control"
                          defaultValue={lastName}
                          onChange={e => setState({lastName: e.currentTarget.value})}
                        />
                      </div>
                    </div>
                    <div className="form-group">
                      <label className="">Bio</label>
                      <input
                        type="hidden"
                        defaultValue={bio}
                        name="bio"
                        id="bio-body"
                      />
                      // <<< having trouble accessing this ref element
                      <trix-editor input="bio-body" ref={trixInput}/>
                    </div>

                    <input type="submit" className="btn btn-primary" value="Update Profile" disabled={loading}/>
                    </form>
                  </article>
                </div>
              )}
            </Mutation>
          );
        }
      }}
    </Query>
  )
}

export default EditProfile;

ОБНОВЛЕНИЕ: Для всех заинтересованных лиц, проблема была решена путем извлечения компонента Mutation в другой файл. Причина была в том, что компонент Mutation не монтировался при рендеринге, монтировался только компонент Query. Первая итерация решения показана в виде ответа.

1 Ответ

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

EditProfile компонент

import React, { useState } from 'react';
import { Query  } from 'react-apollo';
import { useHistory, useParams } from "react-router-dom";
import { GetAuthUser } from './operations.graphql';
import ProfileMutation from './ProfileMutation'


const EditProfile = (props) => {
  const [state, setState] = useState({
                              firstName: "",
                              lastName: "",
                              bio: "",
                              avatar: "",
                              gender: "",
                              country: ""
                            });

  let { username }    = useParams();
  let userFromStore   = JSON.parse(sessionStorage.getItem('_ev'));
  let history         = useHistory();

  if (userFromStore !== username) {
    return (
      <div className="alert">
         <span className="closebtn" onClick={() => history.push("/console")}>&times;</span>
          <strong>Wanning!</strong> Not authorized to access this page.
      </div>
    );
  }
  return (
    <Query query={GetAuthUser}>
      {({ loading, error, data }) => {
        if (loading) return "loading...";
        if (error)   return `Error: ${error}`;

        return <ProfileMutation state={state} profile={data.authUser.profile} setState={setState}/>
      }}
    </Query>
  )
}

export default EditProfile;

ProfileMutation компонент

import React, { useRef, useEffect } from 'react';
import { Mutation } from 'react-apollo';
import { UpdateUserProfile } from './operations.graphql';
import "trix/dist/trix.css";
import "./styles.css"

const ProfileMutation = ({ state, profile, setState }) => {
  const trixInput = useRef('');
  let { userId, firstName, lastName, avatar, bio, gender, country } = profile;
  let userID = parseInt(userId);
  // console.log(firstName)

  useEffect(() => {
   trixInput.current.addEventListener('trix-change', (e) => {
    setState({bio: trixInput.current.value})
      console.log(trixInput.current.value)
    })
  },[trixInput])

  return (
    <Mutation mutation={UpdateUserProfile}>
      {(editProfile, { loading }) => (
        <div  className="card bg-light col-md-8 offset-md-2 shadow p-3 mb-5 rounded">
          <article className="card-body">
            <form onSubmit={ e => {
              e.preventDefault();
              editProfile({
                variables: {
                  userId:    userID,
                  firstName: state.firstName,
                  lastName:  state.lastName,
                  bio:       state.bio,
                  avatar:    state.avatar,
                  gender:    state.gender,
                  country:   state.country
                }
              }).then(({ data: { editProfile: { success, errors }  } }) => {
                success ? alert(success) : alert(errors[0]["message"]);
               //TODO: replace alerts with custom message box
              });
            }}
            >
            <div className="form-row mb-3">
              <div className="col">
                <input
                  type="text"
                  name="firstName"
                  placeholder="First name"
                  className="form-control"
                  defaultValue={firstName}
                  onChange={e => setState({firstName: e.currentTarget.value})}
                />
              </div>
              <div className="col">
                <input
                  type="text"
                  name="lastName"
                  placeholder="Last name"
                  className="form-control"
                  defaultValue={lastName}
                  onChange={e => setState({lastName: e.currentTarget.value})}
                />
              </div>
            </div>
            <div className="form-group">
              <label className="">Bio</label>
              <input
                type="hidden"
                defaultValue={bio}
                name="bio"
                id="bio"
              />
              <trix-editor input="bio" ref={trixInput} />
            </div>

            <input type="submit" className="btn btn-primary" value="Update Profile" disabled={loading}/>
            </form>
          </article>
        </div>
      )}
    </Mutation>
  );
}

export default ProfileMutation;

Надеюсь, это кому-нибудь поможет! Если у кого-то есть лучшее решение, пожалуйста, отправьте его здесь. Спасибо!

...