反应异步状态管理

时间:2020-08-27 22:17:16

标签: javascript reactjs firebase asynchronous react-state-management

我讨厌上传没有沙箱的代码段,但是这个特定的实例我使用Firebase,所以不确定如何制作。对冗长的代码表示歉意。我是React的初学者,现在已经在状态管理问题上停留了2周,我尝试了许多不同的方法,但没有结果。请帮忙。

我的目标是单击AddLinkButton一次制作多个输入表单,每个输入表单将是不同的链接,单击Apply Button它将收集所有链接值并将其存储到firebase的消防站。一旦存储完成,它将通过向<UserPreview />传递多个更新的挂钩值来显示预览。

如果我在下面运行此特定代码,则应为链接输入表单的值的键为null,并且不会在onChange上更新。

请帮助...非常感谢。谢谢。

编辑:将变量名键更改为keyHook,但未成功。相同的问题

const AdminCustomizer = () => {
  const [username, setUsername] = useState(null);
  const [linkForm, setlinkForm] = useState([]);
  const [spotlightLabel, setSpotlightLabel] = useState('');
  const [spotlightLink, setSpotlightLink] = useState('');
  const [refresh, setRefresh] = useState(false);
  const [keyHook, setKeyHook] = useState(null);
  const [startCollect, setStartCollect] = useState(false);
  const linkRef = useRef();
  const userInfo = {username, linkRef, spotlightLabel, spotlightLink, pfpURL, refresh};

  // on initial load, load database to page
  if (!username) {
    firebase.getAuth().onAuthStateChanged(user => {
      if (user) {
        setUsername(user.displayName);
        firebase.getUserInfo(user.displayName).then(result => {
          setSpotlightLabel(result.spotlightLabel);
          setSpotlightLink(result.spotlightLink);
          linkRef.current = result.links;
          if (result.links) {
            Object.values(result.links).forEach(link => {
              AddLinks(link);
            });
          }
        })
      }
    });
  }

  //on refresh (when clicking apply changes button) reload page values with updated database
  useEffect(() => {
    if (refresh) {
      firebase.getAuth().onAuthStateChanged(user => {
        if (user) {
          firebase.getUserInfo(user.displayName).then(result => {
            linkRef.current = result.links;
            Object.values(result.links).forEach(link => {
              AddLinks(link);
            });
          })
          setRefresh(false);
        }
      });
    }
  }, [refresh])
  
  // adding AddLink button will add a new input form
  // adding AddLink with firebase database value will add a new input form with values loaded
  const AddLinks = url => {
    const hooks = { refresh, startCollect, keyHook, setKeyHook };
    if (url) setKeyHook(url);
    setlinkForm([ ...linkForm, <AddLink key={keyHook} keyHook={keyHook} hooks={hooks} /> ]);
  }

  // add link input form
  const AddLink = props => {
    const handleChange = e => setKeyHook(e.target.value);
    return (
      <form noValidate autoComplete="off">
        <br />
        <Link label="Social" onChange={handleChange} value={props.keyHook} /> 
      </form>
    )
  }
  
  // when apply changes is clicked, collect input values from all link input forms
  if (startCollect) { 
    linkForm.forEach(form => {
      linkRef.current = { 
        ...linkRef.current,
        link: form.keyHook,
      }
    });
    firebase.addLinksToUser({ spotlightLabel, spotlightLink, linkRef }).then(() => {
      //force refresh to update userInfo for UserPreview
      setStartCollect(false);
      setRefresh(true);
    });
  }

  return (
      <>
        <LinkBox>
          <ApplyButton onClick={() => setStartCollect(true)}>Apply Changes</ApplyButton>
          <Link label="Website Title" onChange={e => setSpotlightLabel(e.target.value)} value={spotlightLabel} />
          <Link label="Website URL" onChange={e => setSpotlightLink(e.target.value)} value={spotlightLink}/>
          <AddLinkButton onClick={() => AddLinks(null)} />
          <div>{linkForm ? linkForm.map(child => child) : null}</div>
        </LinkBox>
          <div>
            <PhoneOutline>
              <UserPreview userInfo={userInfo}/>
            </PhoneOutline>
          </div>
      </>
  );
}

export default AdminCustomizer;

1 个答案:

答案 0 :(得分:0)

AddLink中,key是一个受限制的关键字,不会作为prop传播。尝试使用其他道具名称代替key

请参见this link

尝试:

<AddLink key={keyHook} keyHook={keyHook} hooks={hooks} />