Реакция ловушки useState не вызывает повторного рендеринга дочернего компонента - PullRequest
0 голосов
/ 26 сентября 2019

У меня есть родительский функциональный компонент <EditCard/>, который является модальным, который открывается при нажатии кнопки редактирования строки таблицы.Эта карточка редактирования содержит переменную состояния с именем data, которая состоит из данных редактируемой строки таблицы.Я устанавливаю / изменяю состояние на <EditCard/> с помощью крюка useState.

<EditCard/> имеет дочерний компонент <CategoryDropdown/>, который представляет собой раскрывающийся список, в котором в качестве выбранного значения принимается реквизит data.assignCategory, и обратный вызов handleChange(), который обновляет значение состояния data, выбрав значение израскрывающийся список.

Когда я выбираю новое значение из раскрывающегося списка, вызывается handleChange() и вызывается setData(), и я вижу, что состояние обновляется, но <CategoryDropdown/> не отображается повторно с новым выбранным значением.

Код компонента EditCard

export default function EditCard(props) {
    const [data, setData] = useState(props.data);

    const handleChange = () => event => {
        let d = data;
        d.assignCategory = event.target.value;
        setData(d);
    };

    let assignCategoryCol = data.assignCategory !== undefined ? <AssignCategoryCol data={data} handleChange={handleChange}/> : <></>;

    return (
        <div>
            {assignCategoryCol}
            <Button>Update</Button>
        </div>
    )
}

{props.data.bucketTotal}`} <Lock/></Typography>)
};

const AssignCategoryCol = (props) => {
    return (
        <CategoryDropdown id={props.data.id} assignedCategory={props.data.assignCategory} handleDropdownChange={props.handleChange}/>)
};

const useStyles = makeStyles(theme => ({}));

Категория Компонент Dropdown

class CategoryDropdown extends Component {
    constructor(props) {
        super(props);
        //TODO Get Categories from DB and set default
        this.state = {
            categories: ['Select One', 'Category1', 'Category2', 'Category3'],
        };
    }

    render() {
        return (
            <div id={'categoryDropdown'}>
                <Select onChange={this.props.handleDropdownChange(this.props.id)} value={this.props.assignedCategory}>
                    {this.state.categories.map((category) => {
                        return <MenuItem value={category}>{category}</MenuItem>
                    })}
                </Select>
            </div>
        )
    }
}


const styles = theme => ({});

export default withStyles(styles)(CategoryDropdown)

1 Ответ

1 голос
/ 26 сентября 2019

Чтобы React узнал, что в состоянии что-то изменилось, вам необходимо заменить текущий объект совершенно новым объектом.В настоящее время реагирует, видит, что это тот же объект, поэтому ничего не делает.Он не ищет объект, чтобы увидеть, изменились ли в нем какие-либо свойства.

В вашем обработчике handleChange у вас есть:

let d = data;

Это не копирование объекта данных.Вместо этого, теперь переменная «d» указывает на тот же объект (в памяти), на который указывает переменная «data».

(Для получения дополнительной информации читайте о передаче «по ссылке» против передачи по значению)").

Чтобы это исправить, см. Деструктуризацию / копирование ниже:

const [data, setData] = useState(props.data)

const handleChange = () => event => {
        let newData = {...data} //copy the object
        newData.assignCategory = event.target.value;
        setData(newData);
 };
...