Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/26.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 它赢了';t在状态更改时重新加载子组件_Javascript_Reactjs_Babeljs - Fatal编程技术网

Javascript 它赢了';t在状态更改时重新加载子组件

Javascript 它赢了';t在状态更改时重新加载子组件,javascript,reactjs,babeljs,Javascript,Reactjs,Babeljs,我正在实现fitness tracker,在呈现子组件时遇到问题,这取决于索引 单击按钮后,训练组件将显示选定索引上的对象,但不会重新渲染。我尝试添加日志,日志中的值正在更改,但它只是没有重新渲染。任何建议都将不胜感激 我的主要功能是 import React, { useState } from "react"; import Workout from "./Workout"; import sampleData from "./sampleData"; export default fun

我正在实现fitness tracker,在呈现子组件时遇到问题,这取决于索引

单击按钮后,训练组件将显示选定索引上的对象,但不会重新渲染。我尝试添加日志,日志中的值正在更改,但它只是没有重新渲染。任何建议都将不胜感激

我的主要功能是

import React, { useState } from "react";
import Workout from "./Workout";
import sampleData from "./sampleData";

export default function App() {
  const [exerciseIndex, setExerciseIndex] = useState(0);
  const [renderWorkout, setRenderWorkout] = useState([
    sampleData[exerciseIndex]
  ]);

  const handleClick = currentIndex => {
    //console.log(currentIndex);
    setExerciseIndex(currentIndex);
    setRenderWorkout(sampleData[exerciseIndex]);
  };

  const navVal = sampleData.map((exercise, index) => {
    return (
      <button key={index} onClick={() => handleClick(index)}>
        {exercise.date}
      </button>
    );
  });

  return (
    <div className="App">
      <h1>Workouts</h1>
      <br />
      {navVal}
      <Workout initialValues={renderWorkout[exerciseIndex]} />
    </div>
  );
}
训练部分

import React, { useReducer } from "react";
import "./styles.css";
import update from "react-addons-update";

/*const initialValues = {
  ...sampleData,
  newExerciseName: ""
};*/

export default function Workout(props) {
  let newData;
  function reducer(state, action) {
    switch (action.type) {
      case "topTextChange":
        return {
          ...state,
          [action.payload.name]: action.payload.value
        };

      case "addSet":
        newData = update(state.workout, {
          [action.payload - 1]: {
            sets: {
              $push: [
                {
                  setId: state.workout[action.payload - 1].sets.length + 1,
                  weight: 0,
                  reps: 0
                }
              ]
            }
          }
        });
        return {
          ...state,
          workout: newData
        };

      case "removeSet":
        newData = update(state.workout, {
          [action.payload - 1]: {
            sets: {
              $splice: [[state.workout[action.payload - 1].sets.length - 1, 1]]
            }
          }
        });
        return {
          ...state,
          workout: newData
        };

      case "addExercise":
        console.log(state);
        newData = update(state.workout, {
          $push: [
            {
              exerciseId: state.workout.length + 1,
              exerciseName: state.newExerciseName,
              sets: []
            }
          ]
        });
        return {
          ...state,
          workout: newData
        };
      case "deleteExercise":
        const position = state.workout.findIndex(
          exercise => exercise.exerciseId === action.payload
        );
        newData = update(state.workout, {
          $splice: [[position, 1]]
        });
        return {
          ...state,
          workout: newData
        };
      default:
        throw new Error();
    }
  }

  const [state, dispatch] = useReducer(reducer, props.data);

  const addExercise = () => dispatch({ type: "addExercise" });
  const deleteExercise = id =>
    dispatch({ type: "deleteExercise", payload: id });

  const changeText = e =>
    dispatch({ type: "topTextChange", payload: e.target });

  const renderedExercise = state.workout.map((exercise, index) => {
    console.log(exercise);

    return <Exercise key={index} exercise={exercise} />;
  });

  function Set(props) {
    // ToDo: hook up below values to states
    return (
      <div>
        <label>
          {" "}
          Weight <input type="text" value={props.weight} />{" "}
        </label>
        <label>
          {" "}
          Reps <input type="text" value={props.rep} />{" "}
        </label>
      </div>
    );
  }

  function Exercise(props) {
    const renderedSet = props.exercise.sets.map((set, index) => (
      <Set key={index} weight={set.weight} rep={set.reps} />
    ));

    const addSet = id => dispatch({ type: "addSet", payload: id });
    const deleteSet = id => dispatch({ type: "removeSet", payload: id });

    return (
      <div>
        {props.exercise.exerciseName}
        <button onClick={() => deleteExercise(props.exercise.exerciseId)}>
          {" "}
          Remove Exercise{" "}
        </button>
        <button onClick={() => addSet(props.exercise.exerciseId)}>
          {" "}
          Add Set{" "}
        </button>
        <button onClick={() => deleteSet(props.exercise.exerciseId)}>
          Remove Set
        </button>
        {renderedSet}
      </div>
    );
  }

  return (
    <div className="Workout">
      {renderedExercise}
      <br />
      <br />
      <input
        type="text"
        name="newExerciseName"
        value={state.newExerciseName}
        placeholder="What exercise do you want to add?"
        onChange={e => changeText(e)}
      />{" "}
      <button onClick={() => addExercise()}>Add Exercise</button>
    </div>
  );
}
import React,{useReducer}来自“React”;
导入“/styles.css”;
从“react插件更新”导入更新;
/*常量初始值={
…采样数据,
newExerciseName:“
};*/
导出默认功能训练(道具){
让新数据;
功能减速机(状态、动作){
开关(动作类型){
案例“topTextChange”:
返回{
……国家,
[action.payload.name]:action.payload.value
};
案例“addSet”:
newData=更新(state.workout{
[action.payload-1]:{
设置:{
$push:[
{
setId:state.workout[action.payload-1].sets.length+1,
重量:0,,
销售代表:0
}
]
}
}
});
返回{
……国家,
训练:新数据
};
案例“removeSet”:
newData=更新(state.workout{
[action.payload-1]:{
设置:{
$splice:[[state.workout[action.payload-1].sets.length-1,1]]
}
}
});
返回{
……国家,
训练:新数据
};
案例“addExercise”:
console.log(状态);
newData=更新(state.workout{
$push:[
{
exerciseId:state.workout.length+1,
exerciseName:state.newExerciseName,
集合:[]
}
]
});
返回{
……国家,
训练:新数据
};
案例“删除练习”:
const position=state.workout.findIndex(
exercise=>exercise.exerciseId==action.payload
);
newData=更新(state.workout{
$splice:[[位置,1]]
});
返回{
……国家,
训练:新数据
};
违约:
抛出新错误();
}
}
const[state,dispatch]=useReducer(reducer,props.data);
const addExercise=()=>dispatch({type:“addExercise”});
const deleteExecution=id=>
分派({type:“deleteExecution”,有效负载:id});
const changeText=e=>
分派({type:“topTextChange”,有效负载:e.target});
const renderedExercise=state.workout.map((练习,索引)=>{
控制台日志(练习);
返回;
});
功能集(道具){
//ToDo:将以下值连接到状态
返回(
{" "}
权重{'}
{" "}
代表{“}
);
}
功能练习(道具){
const renderedSet=props.exercise.sets.map((集合,索引)=>(
));
const addSet=id=>dispatch({type:“addSet”,payload:id});
constdeleteset=id=>dispatch({type:“removeSet”,payload:id});
返回(
{props.exercise.exerciseName}
deleteExercise(props.exercise.exerciseId)}>
{" "}
删除练习{“”}
addSet(props.exercise.exerciseId)}>
{" "}
添加集{“”}
deleteSet(props.exercise.exerciseId)}>
移除集
{renderedSet}
);
}
返回(
{renderedExercise}


changeText(e)} />{" "} addExercise()}>添加练习 ); }
谢谢,
杰克

我找到了解决办法。问题是因为我在子组件“训练”中有状态,并且我没有更新它,因为它已从父组件“应用”更改。我使用forwardRef、useRef和UseImperialiveHandle从父组件更新状态。现在它正在按预期工作。有关更新的实施,请参见下文。有关这些钩子的更多信息,请查看官方的ReactJS指南或是我找到解决方案的地方

App.js

import React, { useState, useRef } from "react";
import Workout from "./Workout";
import sampleData from "./sampleData";

export default function App() {
  const workoutRef = useRef(null);

  const navVal = sampleData.map((exercise, index) => {
    return (
      <button key={index} onClick={() => handleClick(index)}>
        {exercise.date}
      </button>
    );
  });

  const handleClick = currentIndex => {
    workoutRef.current.updateExercise(sampleData[currentIndex]);
  };

  return (
    <div className="App">
      <h1>Workouts</h1>
      <br />
      {navVal}
      <Workout ref={workoutRef} data={sampleData[0]} />
    </div>
  );
}
import React,{useState,useRef}来自“React”;
从“/Workout”导入训练;
从“/sampleData”导入sampleData;
导出默认函数App(){
const workoutRef=useRef(null);
const navVal=sampleData.map((练习,索引)=>{
返回(
handleClick(索引)}>
{练习日期}
);
});
const handleClick=currentIndex=>{
workutref.current.updateExercise(sampleData[currentIndex]);
};
返回(
运动

{navVal} ); }
Workout.js

import React, { useReducer, forwardRef, useImperativeHandle } from "react";
import "./styles.css";
import update from "react-addons-update";

const Workout = forwardRef((props, ref) => {
  let newData;
  function reducer(state, action) {
    switch (action.type) {
      case "topTextChange":
        return {
          ...state,
          [action.payload.name]: action.payload.value
        };

      case "addSet":
        newData = update(state.workout, {
          [action.payload - 1]: {
            sets: {
              $push: [
                {
                  setId: state.workout[action.payload - 1].sets.length + 1,
                  weight: 0,
                  reps: 0
                }
              ]
            }
          }
        });
        return {
          ...state,
          workout: newData
        };

      case "removeSet":
        newData = update(state.workout, {
          [action.payload - 1]: {
            sets: {
              $splice: [[state.workout[action.payload - 1].sets.length - 1, 1]]
            }
          }
        });
        return {
          ...state,
          workout: newData
        };

      case "addExercise":
        console.log(state);
        newData = update(state.workout, {
          $push: [
            {
              exerciseId: state.workout.length + 1,
              exerciseName: state.newExerciseName,
              sets: []
            }
          ]
        });
        return {
          ...state,
          workout: newData
        };
      case "deleteExercise":
        const position = state.workout.findIndex(
          exercise => exercise.exerciseId === action.payload
        );
        newData = update(state.workout, {
          $splice: [[position, 1]]
        });
        return {
          ...state,
          workout: newData
        };
      case "replaceExercise":
        return {
          ...action.payload
        };
      default:
        throw new Error();
    }
  }

  const [state, dispatch] = useReducer(reducer, props.data);

  const addExercise = () => dispatch({ type: "addExercise" });
  const deleteExercise = id =>
    dispatch({ type: "deleteExercise", payload: id });

  const changeText = e =>
    dispatch({ type: "topTextChange", payload: e.target });

  const renderedExercise = state.workout.map((exercise, index) => {
    return <Exercise key={index} exercise={exercise} />;
  });

  const updateExercise = data => {
    dispatch({ type: "replaceExercise", payload: data });
  };

  useImperativeHandle(ref, () => {
    return {
      updateExercise: updateExercise
    };
  });

  function Set(props) {
    // ToDo: hook up below values to states
    return (
      <div>
        <label>
          {" "}
          Weight <input type="text" value={props.weight} />{" "}
        </label>
        <label>
          {" "}
          Reps <input type="text" value={props.rep} />{" "}
        </label>
      </div>
    );
  }

  function Exercise(props) {
    const renderedSet = props.exercise.sets.map((set, index) => (
      <Set key={index} weight={set.weight} rep={set.reps} />
    ));

    const addSet = id => dispatch({ type: "addSet", payload: id });
    const deleteSet = id => dispatch({ type: "removeSet", payload: id });

    return (
      <div>
        {props.exercise.exerciseName}
        <button onClick={() => deleteExercise(props.exercise.exerciseId)}>
          {" "}
          Remove Exercise{" "}
        </button>
        <button onClick={() => addSet(props.exercise.exerciseId)}>
          {" "}
          Add Set{" "}
        </button>
        <button onClick={() => deleteSet(props.exercise.exerciseId)}>
          Remove Set
        </button>
        {renderedSet}
      </div>
    );
  }

  return (
    <div className="Workout">
      {renderedExercise}
      <br />
      <br />
      <input
        type="text"
        name="newExerciseName"
        value={state.newExerciseName}
        placeholder="What exercise do you want to add?"
        onChange={e => changeText(e)}
      />{" "}
      <button onClick={() => addExercise()}>Add Exercise</button>
    </div>
  );
});

export default Workout;
import React,{useReducer,forwardRef,useImperialiveHandle}来自“React”;
导入“/styles.css”;
从“react插件更新”导入更新;
常量训练=前进参考((道具,参考)=>{
让新数据;
功能减速机(状态、动作){
开关(动作类型){
案例“topTextChange”:
返回{
……国家,
[action.payload.name]:action.payload.value
};
案例“addSet”:
newData=更新(state.workout{
[action.payload-1]:{
设置:{
$push:[
{
setId:state.workout[action.payload-1].sets.length+1,
重量:0,,
销售代表:0
}
]
}
}
});
返回{
……国家,
训练:新数据
};
案例“removeSet”:
newData=更新(state.workout{
[action.payload-1]:{
设置:{
$splice:[[state.workout[action.payload-1].sets.length-1,1]]
}
}
});
返回{
……国家,
训练:新数据
};
C
import React, { useReducer, forwardRef, useImperativeHandle } from "react";
import "./styles.css";
import update from "react-addons-update";

const Workout = forwardRef((props, ref) => {
  let newData;
  function reducer(state, action) {
    switch (action.type) {
      case "topTextChange":
        return {
          ...state,
          [action.payload.name]: action.payload.value
        };

      case "addSet":
        newData = update(state.workout, {
          [action.payload - 1]: {
            sets: {
              $push: [
                {
                  setId: state.workout[action.payload - 1].sets.length + 1,
                  weight: 0,
                  reps: 0
                }
              ]
            }
          }
        });
        return {
          ...state,
          workout: newData
        };

      case "removeSet":
        newData = update(state.workout, {
          [action.payload - 1]: {
            sets: {
              $splice: [[state.workout[action.payload - 1].sets.length - 1, 1]]
            }
          }
        });
        return {
          ...state,
          workout: newData
        };

      case "addExercise":
        console.log(state);
        newData = update(state.workout, {
          $push: [
            {
              exerciseId: state.workout.length + 1,
              exerciseName: state.newExerciseName,
              sets: []
            }
          ]
        });
        return {
          ...state,
          workout: newData
        };
      case "deleteExercise":
        const position = state.workout.findIndex(
          exercise => exercise.exerciseId === action.payload
        );
        newData = update(state.workout, {
          $splice: [[position, 1]]
        });
        return {
          ...state,
          workout: newData
        };
      case "replaceExercise":
        return {
          ...action.payload
        };
      default:
        throw new Error();
    }
  }

  const [state, dispatch] = useReducer(reducer, props.data);

  const addExercise = () => dispatch({ type: "addExercise" });
  const deleteExercise = id =>
    dispatch({ type: "deleteExercise", payload: id });

  const changeText = e =>
    dispatch({ type: "topTextChange", payload: e.target });

  const renderedExercise = state.workout.map((exercise, index) => {
    return <Exercise key={index} exercise={exercise} />;
  });

  const updateExercise = data => {
    dispatch({ type: "replaceExercise", payload: data });
  };

  useImperativeHandle(ref, () => {
    return {
      updateExercise: updateExercise
    };
  });

  function Set(props) {
    // ToDo: hook up below values to states
    return (
      <div>
        <label>
          {" "}
          Weight <input type="text" value={props.weight} />{" "}
        </label>
        <label>
          {" "}
          Reps <input type="text" value={props.rep} />{" "}
        </label>
      </div>
    );
  }

  function Exercise(props) {
    const renderedSet = props.exercise.sets.map((set, index) => (
      <Set key={index} weight={set.weight} rep={set.reps} />
    ));

    const addSet = id => dispatch({ type: "addSet", payload: id });
    const deleteSet = id => dispatch({ type: "removeSet", payload: id });

    return (
      <div>
        {props.exercise.exerciseName}
        <button onClick={() => deleteExercise(props.exercise.exerciseId)}>
          {" "}
          Remove Exercise{" "}
        </button>
        <button onClick={() => addSet(props.exercise.exerciseId)}>
          {" "}
          Add Set{" "}
        </button>
        <button onClick={() => deleteSet(props.exercise.exerciseId)}>
          Remove Set
        </button>
        {renderedSet}
      </div>
    );
  }

  return (
    <div className="Workout">
      {renderedExercise}
      <br />
      <br />
      <input
        type="text"
        name="newExerciseName"
        value={state.newExerciseName}
        placeholder="What exercise do you want to add?"
        onChange={e => changeText(e)}
      />{" "}
      <button onClick={() => addExercise()}>Add Exercise</button>
    </div>
  );
});

export default Workout;