Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/398.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 错误:尝试设置状态时重新渲染过多_Javascript_Reactjs - Fatal编程技术网

Javascript 错误:尝试设置状态时重新渲染过多

Javascript 错误:尝试设置状态时重新渲染过多,javascript,reactjs,Javascript,Reactjs,这是我的代码: import React, {useState, useEffect} from 'react'; import './App.css'; import {Table, Button, InputGroup, FormControl} from 'react-bootstrap'; import {PonCard} from "./components/PonCard"; function App() { const [pons, setPons] = useState(n

这是我的代码:

import React, {useState, useEffect} from 'react';
import './App.css';
import {Table, Button, InputGroup, FormControl} from 'react-bootstrap';
import {PonCard} from "./components/PonCard";

function App() {
  const [pons, setPons] = useState(null);
  const [translations, setTranslations] = useState(null);
  const [isInEditMode, setIsInEditMode] = useState(false);
  const [inputValue, setInputValue] = useState('');
  const [errors, setErrors] = useState([]);
  const [translationsToSave, setTranslationsToSave] = useState([]);

  const changeIsInEditMode = () => setIsInEditMode(!isInEditMode);
  const handleEditButtonClick = (id) => console.log('Edit', id);
  const handleDeleteButtonClick = (id) => console.log('Delete', id);
  const handleInputChange = (e) => setInputValue(e.target.value);
  const handleFetchOnButtonClick = async () => {
    const resp = await fetch(`http://localhost:8080/pons/findTranslation/${inputValue}`).then(r => r.json()).catch(e => console.log(e));
    if (resp.ok === true) {
      setTranslations(resp.resp[0].hits);
      setErrors([]);
    } else {
      setErrors(resp.errors ? resp.errors : ['Something went wrong. check the input']);
    }
  };
  const handleSaveTranslations = async () => {
    const resp = await fetch('http://localhost:8080/pons/', {
      method: 'POST',
      body: JSON.stringify({original: inputValue, translations: translationsToSave}),
      mode: 'cors',
      headers: {
        'Content-Type': 'application/json',
      }
    }).then(r => r.json())
      .catch(e => {
        console.log(e);
        return {ok: false};
      });
    setInputValue('');
    setTranslations(null);
    if (resp.errors) {
      setErrors(resp.errors);
    }
  };

  useEffect(() => {
    fetch('http://localhost:8080/pons/')
      .then(r => r.json())
      .then(resp => {
        if (resp.ok === true) {
          setPons(resp.pons);
        } else {
          setErrors(resp.errors);
        }
      })
      .catch(e => console.log(e));
  }, []);

  return (
    <div className="App">
      <InputGroup className="mb-3">
        <FormControl
          value={inputValue}
          onChange={handleInputChange}
          placeholder={inputValue}
        />
      </InputGroup>

      <div className="mb-3">
        <Button onClick={handleFetchOnButtonClick} disabled={inputValue === '' || errors.length > 0}>Translate</Button>
        <Button onClick={changeIsInEditMode}>
          {isInEditMode ? 'Exit edit mode' : 'Enter edit mode'}
        </Button>

        <Button disabled={translationsToSave.length === 0} onClick={handleSaveTranslations}>Save translations</Button>
      </div>
      {errors.length > 0 ? errors.map(e => <div key={e}>{e}</div>) : null}
      {
        pons && !translations && inputValue === '' ? pons.map(pon => <PonCard key={Math.random()} {...{pon}}/>) : null
      }
      {
        translations ?
          <Table striped bordered hover>
            <thead>
            <tr>
              <th>Original</th>
              <th>Translation</th>
              <th>Actions</th>
            </tr>
            </thead>
            <tbody>
            {
              translations.map(pon => pon.roms.map(rom => rom.arabs.map(arab => arab.translations.map(translation => {
                const {source, target} = translation;
                return (
                  <tr key={Math.random()}>
                    <td><span dangerouslySetInnerHTML={{__html: source}}/></td>
                    <td><span dangerouslySetInnerHTML={{__html: target}}/></td>
                    <td>
                      {
                        !translationsToSave.includes(target) ?
                          <Button onClick={() => {
                            setTranslationsToSave(prev => [...prev, target]);
                          }}>
                            Add translation
                          </Button>
                          :
                          <Button
                            onClick={() => {
                              setTranslationsToSave((prev) => {
                                const index = prev.findIndex(elem => elem === target)
                                return [...prev.slice(0, index), ...prev.slice(index + 1)]
                              });
                            }}>
                            Remove translation
                          </Button>
                      }
                    </td>
                  </tr>
                )
              }))))
            }
            </tbody>
          </Table>
          : (
            <span>No translations</span>
          )
      }
    </div>
  );
}

export default App;
我要做的是获取挂载上的数据。我发现这是模仿
componentDidMount

useEffect(() => {
  fetch('http://localhost:8080/pons/')
    .then(r => r.json())
    .then(resp => {
      if (resp.ok === true) {
        setPons(resp.pons);
      } else {
        setErrors(resp.errors);
      }
    })
    .catch(e => console.log(e));
}, []);
但我明白了

错误:重新渲染过多。React限制渲染的数量以防止无限循环

一直如此

  106 | .then(r => r.json())
  107 | .then(resp => {
  108 |   if (resp.ok === true) {
> 109 |     setPons(resp.pons);
      | ^  110 |   } else {
  111 |     setErrors(resp.errors);
  112 |   }

它指向
setPons
方法,这没有意义,因为它在装载时只更新一次。我遗漏了什么?

问题是PonCard中的这一行:

const handleClick = setIsFlipped(!isFlipped);
每次PonCard渲染时,该行将立即切换其翻转状态,从而再次渲染并再次翻转,依此类推。您可能打算这样做:

const handleClick = () => setIsFlipped(!isFlipped);
错误消息指向
setPons
的原因只是因为这是启动它的第一个设置状态。在此之前,没有渲染PonCard,因此没有无限循环的PonCard渲染

const handleClick = () => setIsFlipped(!isFlipped);