Реакция функциональных компонентов без состояния - Laravel - PullRequest
0 голосов
/ 25 января 2020

Я настроил проект с laravel в качестве бэкэнд-провайдера Api и React в качестве Frontend-менеджера. Реагирующий функциональный компонент без состояния хорошо работает, когда я просто отображаю какой-либо компонент.

const [state, setState] = useState({data:someData})

Я использую useEffect для извлечения некоторых данных с помощью Ax ios из URL-адреса API. отлично

Но когда я меняю состояние компонента с помощью setState, он не работает. Никаких изменений не отражено. это выглядит как stati c страница, даже если я нажму 100 раз кнопку с событием нажатия. консоль понятна. Без ошибок

Хочу знать почему? и как я могу это исправить.

Примечание: Компонент на основе классов не имеет этой проблемы. он отлично отображает любое обновление состояния

Некоторые коды

const Users = (props) => {

const [state, setState] = useState({

    dataPraticiens: {
        data: [],
        currentPage: 1,
        PerPage: 3
    },
    loaded: false

});


useEffect(() => {
    Axios.get('/api/users').then((r) => {

        setState({

            dataPraticiens: {
                data: [...r.data.docs],
                currentPage: 1,
                PerPage: 3
            } ,

            loaded: true
        });

    }).catch((er)=> {
        console.log(er);
    })

},[state.loaded]);

const changePage = (event) => {

    let nS = state;
    nS.dataPraticiens.currentPage = Number(event.target.id);
    nS.loaded = false;
    setState(nS); 
    // log the state and yeah, state changes but not reflected in the page
}


const indexOfLast = state.dataPraticiens.currentPage * state.dataPraticiens.PerPage;

const indexOfFirst = indexOfLast - state.dataPraticiens.PerPage;

const current = state.dataPraticiens.data.slice(indexOfFirst, indexOfLast);


const pageN = [];
for (let i = 1; i <= Math.ceil(state.dataPraticiens.data.length / state.dataPraticiens.PerPage); i++) {
    pageN.push(i);
}

const renderPageN = pageN.map(num => {
    return (
        <li
            key={num}
            id={num}
            onClick={changePage} // Not work here.
        >
            {num}
        </li>
    );
});
return (
        {current.map((value, index) => {
           return <React.Fragment key={index}>
                     <li>{value}</li>
                  </React.Fragment>
         })}
        <ul>
          {renderPageN} // pages number`
        </ul>

     )}

1 Ответ

3 голосов
/ 25 января 2020

В useEffect вы должны использовать пустой массив [], чтобы указать, что вы хотите, чтобы эффект выполнялся только один раз. Использование [state.loaded] будет сбрасывать состояние при каждом обновлении состояния, поскольку обновление состояния вызовет изменение в state.loaded, и это изменение вызовет ловушку эффекта.

Другое дело, что вы не должны изменять состояние напрямую здесь:

let nS = state;
nS.dataPraticiens.currentPage = Number(event.target.id);
nS.loaded = false;
setState(nS);

Обратите внимание, что nS - это просто ссылка на тот же объект состояния, так что вы напрямую модифицируете состояние, что может привести к неопределенному поведению и странным ошибкам. Вы должны создать новую копию объекта состояния:

const newState = {
  dataPraticiens: {
    ...state.dataPraticiens,
    currentPage: Number(event.target.id)
  }, 
  loaded: false
};

setState(newState);

Из документа Документы :

НИКОГДА мутировать this.state напрямую, так как вызов setState() впоследствии может заменить сделанную вами мутацию. Относитесь к this.state как к неизменному.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...