繁体   English   中英

state 更改后反应不重新渲染

[英]react not rerendering after state change

我知道有类似的问题,但我有一个奇怪的问题。

这就是我正在做的

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

function App() {
  const [pons, setPons] = useState();
  const [translations, setTranslations] = useState([]);
  const [isInEditMode, setIsInEditMode] = useState(false);
  const [inputValue, setInputValue] = useState('samochod');
  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('localhost:8080/pons/', {method: 'POST', body: {content: translationsToSave}});
    if (resp.ok === true) {
      setInputValue('');
      setTranslations(null);
    }
  };

  return (
    <div className="App">
      {errors.length > 0 ? errors.map(e => <div key={e}>{e}</div>) : null}
      <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>
      <Table striped bordered hover>
        <thead>
        <tr>
          <th>Original</th>
          <th>Translation</th>
          <th>Actions</th>
        </tr>
        </thead>
        <tbody>
        {translations ? translations.map(pon => pon.roms.map(rom => rom.arabs.map(arab => arab.translations.map(translation => {
          const {source, target} = translation;
          return (
            <tr>
              <td><span dangerouslySetInnerHTML={{__html: source}}/></td>
              <td><span dangerouslySetInnerHTML={{__html: target}}/></td>
              <td>
                {
                  !translationsToSave.includes(target) ?
                    <Button onClick={() => {
                      const tmp = translationsToSave;
                      tmp.push(target);
                      setTranslationsToSave(tmp);
                    }}>
                      Add translation
                    </Button>
                    :
                    <Button
                      onClick={() => {
                        const tmp = translationsToSave;
                        tmp.splice(tmp.findIndex(elem => elem === target));
                        setTranslationsToSave(tmp);
                      }}>
                      Remove translation
                    </Button>
                }
              </td>
            </tr>
          )
        })))) : (
          <div>No translations</div>
        )}
        </tbody>
      </Table>
    </div>
  );
}

export default App;

所以它是一个基本的应用程序,它现在只是在数组中添加和删除setTranslationsToSave 单击“ Add translation ”按钮后,视图保持不变。 但是当我单击Enter edit mode时它会刷新。 Remove translation相同。 我需要点击Enter/Exit edit mode

点击Translate也会重新加载视图。 所以Add/Remove translation按钮是唯一不刷新页面的按钮。 为什么? 我错过了什么?

问题是您正在更改添加/删除翻译按钮中的 satte,因此在重新渲染之前进行反应检查时,如果使用相同的 state 调用 state 更新程序,它会感觉没有任何变化,因为它进行了参考检查,因此没有t 触发重新渲染

此外,在基于以前的 state 更新当前 state 时, functional callback approach for state updater

如下更新您的 state

  <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>

在您的Add translation点击处理程序中,您正在改变 state:

<Button onClick={() => {
    // tmp is just a reference to state
    const tmp = translationsToSave;
    // You are mutating state, this will be lost
    tmp.push(target);
    setTranslationsToSave(tmp);
}}>

您应该复制 state 并添加新元素:

<Button onClick={() => {
    setTranslationsToSave([...translationsToSave, target]);
}}>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM