Функциональные компоненты React без сохранения состояния - Laravel

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

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

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

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

Я хочу знать, почему? и как это исправить.

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

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

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>

     )}

person Arnaud    schedule 25.01.2020    source источник
comment
Добавьте свой код для лучшего понимания.   -  person Afia    schedule 25.01.2020
comment
Код добавлен. Благодарность   -  person Arnaud    schedule 25.01.2020
comment
Это не похоже на настоящий функциональный компонент. Куда вы возвращаете то, что он должен рендерить?   -  person mzedeler    schedule 25.01.2020
comment
Спасибо за внимание ????????????   -  person Arnaud    schedule 25.01.2020


Ответы (1)


В 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);

Из документации React:

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

person ahmad    schedule 25.01.2020